IOkrw.mint

mint(address recipient, uint256 amount) external returns (bool)

amount만큼의 OKRW를 발행하여 recipient에게 입금합니다. 금액 단위는 소수점 18자리 base denom인 aokrw입니다. x/okrw 모듈 파라미터에 지정된 발행자 주소만 호출에 성공하며, 그 외 호출자는 모듈 소유 커스텀 오류 UnauthorizedMinter(address caller, address authorizedMinter)로 revert됩니다. recipient가 0 주소이거나 amount가 0이면 공통 오류 IPrecompile.InvalidAddress(string bad)IPrecompile.InvalidAmount(string amount)로 각각 revert됩니다. 두 오류 모두 페이로드가 address 또는 uint256이 아니라 문자열로 표현된 값이라는 점에 주의합니다. amount가 nil이거나 음수인 경우(저수준 ABI 조작으로만 도달 가능)는 커스텀 오류가 아니라 각각 "amount must not be nil", "amount must not be negative"라는 일반 문자열 revert로 처리됩니다.

파라미터

이름 타입 필수 설명
recipient address 새로 발행된 OKRW를 받을 주소입니다. 0 주소여서는 안 되며, 0x0을 전달하면 IPrecompile.InvalidAddress(bad)로 revert됩니다. bad는 0 주소를 문자열로 표현한 값입니다.
amount uint256 발행할 수량이며 aokrw(소수점 18자리, 1 OKRW = 10^18 aokrw — okrw-precompile-overview 참고) 단위입니다. 반드시 0보다 커야 합니다. 0을 전달하면 IPrecompile.InvalidAmount(amount)로 revert되며 페이로드는 금액을 10진수 문자열로 표현한 값입니다. nil이거나 음수인 big.Int 입력(저수준 ABI 조작으로만 도달 가능)은 디코딩 가능한 커스텀 오류가 아니라 "amount must not be nil" 또는 "amount must not be negative"라는 일반 문자열로 revert됩니다.

반환값

타입: bool

성공 시 true를 반환합니다. 실패는 false 반환이 아니라 커스텀 오류로 revert됩니다. Solidity에서 도달할 수 없는 nil/음수 케이스는 일반 문자열 revert로 처리됩니다.

에러

코드 이름 설명
UnauthorizedMinter UnauthorizedMinter msg.sender가 지정된 발행자 주소가 아닐 때 revert됩니다. UnauthorizedMinter(address caller, address authorizedMinter) 형태로 인코딩되어 있어, 클라이언트가 실패한 호출자와 현재 지정된 발행자를 함께 표시할 수 있습니다. IOkrw가 소유하는 오류입니다.
InvalidAddress InvalidAddress recipient가 0 주소일 때(또는 발신자 주소를 인코딩할 수 없을 때) revert됩니다. IPrecompile에서 상속되며 InvalidAddress(string bad) 형태로 인코딩됩니다. 페이로드는 address 타입이 아니라 16진수 문자열로 표현된 주소입니다. 이전에는 InvalidAddress(address)로 디코딩했으므로 ABI 조각을 새 string 형태로 갱신합니다.
InvalidAmount InvalidAmount amount가 정확히 0일 때 revert됩니다. IPrecompile에서 상속되며 InvalidAmount(string amount) 형태로 인코딩됩니다. 페이로드는 uint256이 아니라 금액을 10진수 문자열로 표현한 값입니다. nil이거나 음수 big.Int 입력(저수준 ABI 조작으로만 도달 가능)은 이 커스텀 오류가 아니라 일반 문자열 revert("amount must not be nil" 또는 "amount must not be negative")로 처리됩니다.
UnknownMethod UnknownMethod ABI 인코딩된 메서드 selector가 프리컴파일의 어떤 함수와도 일치하지 않을 때 revert됩니다. IPrecompileUnknownMethod(string methodName)을 상속합니다. Solidity에서 노출되는 경우는 드물며, 보통 ABI가 불일치하거나 오래된 상황을 의미합니다.
InvalidNumberOfArgs InvalidNumberOfArgs 프리컴파일이 메서드 시그니처와 다른 인자 개수를 받을 때 revert됩니다. IPrecompileInvalidNumberOfArgs(uint256 expected, uint256 got)을 상속합니다.
SDKUnauthorized SDKUnauthorized IPrecompile에서 상속됩니다. 하부 체인 계층의 권한 검사가 발행자 불일치(별도의 UnauthorizedMinter로 보고) 외의 이유로 호출을 거절할 때 노출됩니다.

예제

지정된 발행자 컨트랙트에서 기본 발행

프리컴파일 측 권한 검사가 msg.sender와 지정된 발행자를 비교하므로, 이 호출이 성공하려면 Treasury 자신의 주소가 발행자로 지정되어 있어야 합니다.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.28;

import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
import {IPrecompile} from "@maroo-chain/contracts/precompiles/common/interfaces/IPrecompile.sol";

contract Treasury {
    address constant OKRW_PRECOMPILE = 0x1000000000000000000000000000000000000001;
    IOkrw okrw = IOkrw(OKRW_PRECOMPILE);

    /// @notice Mint OKRW to `to`. This contract's address must be the
    ///         authorized minter in the x/okrw module parameters.
    function mintTo(address to, uint256 amount) external {
        // 10_000_000 OKRW == 10_000_000 * 10**18 aokrw when caller passes ether units.
        bool ok = okrw.mint(to, amount);
        require(ok, "OKRW mint returned false");
    }
}

viem으로 클라이언트에서 커스텀 오류 처리 (갱신된 오류 형태)

공유 오류 리팩터링 이후 InvalidAddressInvalidAmountIPrecompile에서 상속되며 단일 string 인자를 가집니다. 이전에 InvalidAddress(address) / InvalidAmount(uint256)로 선언한 ABI 조각을 갱신해야 합니다. 그렇지 않으면 decodeErrorResult가 4바이트 selector를 매칭하지 못하고 revert가 인식되지 않은 오류로 노출됩니다.

import { createWalletClient, http, parseEther, decodeErrorResult } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const OKRW = "0x1000000000000000000000000000000000000001" as const;

// NOTE: InvalidAddress / InvalidAmount now carry a `string` payload, not
// the old `address` / `uint256` — they come from IPrecompile after the
// shared-error refactor. UnauthorizedMinter is still owned by IOkrw.
const okrwAbi = [
  { type: "function", name: "mint", stateMutability: "nonpayable",
    inputs: [{ name: "recipient", type: "address" }, { name: "amount", type: "uint256" }],
    outputs: [{ type: "bool" }] },
  { type: "error", name: "UnauthorizedMinter",
    inputs: [{ name: "caller", type: "address" }, { name: "authorizedMinter", type: "address" }] },
  { type: "error", name: "InvalidAddress", inputs: [{ name: "bad", type: "string" }] },
  { type: "error", name: "InvalidAmount", inputs: [{ name: "amount", type: "string" }] },
] as const;

const wallet = createWalletClient({
  account: privateKeyToAccount(process.env.MINTER_KEY as `0x${string}`),
  transport: http("https://rpc-testnet.maroo.io"),
});

try {
  await wallet.writeContract({
    address: OKRW,
    abi: okrwAbi,
    functionName: "mint",
    // TODO: replace with the real treasury recipient before production.
    args: ["0x8F3ac2B1d9E74c05A6B18FE27Dc4913e5A0F7b62", parseEther("10000000")],
  });
} catch (err: any) {
  if (err?.data) {
    const decoded = decodeErrorResult({ abi: okrwAbi, data: err.data });
    // decoded.errorName is one of UnauthorizedMinter | InvalidAddress | InvalidAmount
    // (plus any inherited IPrecompile error like UnknownMethod / InvalidNumberOfArgs).
    console.error(`OKRW.mint reverted: ${decoded.errorName}`, decoded.args);
  } else {
    // Plain string reverts (nil/negative amount) land here.
    throw err;
  }
}

Solidity의 try/catch로 커스텀 오류 처리

분기의 근거인 4바이트 selector는 여전히 안정적입니다. 달라진 부분은 InvalidAddress / InvalidAmount의 인자 타입으로, 이제 string으로 디코드됩니다. 온체인 selector 분기는 그대로 동작하지만, 페이로드를 ABI 디코드하는 오프체인 소비자는 갱신이 필요합니다.

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.28;

import "@maroo-chain/contracts/precompiles/okrw/IOkrw.sol";
import {IPrecompile} from "@maroo-chain/contracts/precompiles/common/interfaces/IPrecompile.sol";
// InvalidAddress / InvalidAmount are INHERITED from IPrecompile, so they are
// referenced through IPrecompile — IOkrw.InvalidAddress does not compile.

contract SafeMinter {
    IOkrw constant okrw = IOkrw(0x1000000000000000000000000000000000000001);

    event MintFailed(bytes4 selector);

    function safeMint(address to, uint256 amount) external {
        try okrw.mint(to, amount) returns (bool ok) {
            require(ok, "mint returned false");
        } catch (bytes memory raw) {
            bytes4 sel;
            assembly { sel := mload(add(raw, 32)) }

            if (sel == IOkrw.UnauthorizedMinter.selector) {
                emit MintFailed(sel);
            } else if (sel == IPrecompile.InvalidAddress.selector) {
                // Now InvalidAddress(string bad) — inherited from IPrecompile.
                emit MintFailed(sel);
            } else if (sel == IPrecompile.InvalidAmount.selector) {
                // Now InvalidAmount(string amount) — inherited from IPrecompile.
                emit MintFailed(sel);
            } else {
                // Unknown revert (e.g. plain-string revert on nil amount) — bubble up.
                assembly { revert(add(raw, 32), mload(raw)) }
            }
        }
    }
}
ESC
검색어를 입력하세요