Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xACF3c07BeBd65d5f7d86bc0bc716026A0C523069
Balance 0 ETH
Nonce 1
Code Size 3785 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3785 bytes
0x608060405234801561000f575f5ffd5b506004361061012f575f3560e01c806370a08231116100ad578063bf353dbb1161007d578063dd62ed3e11610063578063dd62ed3e1461033a578063e2fdcc171461034f578063ff10ebc614610376575f5ffd5b8063bf353dbb146102f4578063ccba5cd814610313575f5ffd5b806370a082311461028257806395d89b41146102955780639c52a7f1146102ce578063a9059cbb146102e1575f5ffd5b806323b872dd11610102578063313ce567116100e8578063313ce567146101ed57806365fae35e146102265780636f307dc31461023b575f5ffd5b806323b872dd146101c75780632f4f21e2146101da575f5ffd5b806306fdde0314610133578063095ea7b31461017e57806318160ddd146101a4578063205c2878146101b4575b5f5ffd5b60408051808201909152601281527f43656e7472696675676520494f5520434647000000000000000000000000000060208201525b6040516101759190610d46565b60405180910390f35b61019461018c366004610dc1565b600192915050565b6040519015158152602001610175565b5f5b604051908152602001610175565b6101946101c2366004610dc1565b61039d565b6101946101d5366004610de9565b6106b5565b6101946101e8366004610dc1565b61094d565b6102147f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610175565b610239610234366004610e23565b610bb1565b005b7f000000000000000000000000c221b7e65ffc80de234bbb6667abdd46593d34f05b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610175565b6101a6610290366004610e23565b505f90565b60408051808201909152600681527f696f7543464700000000000000000000000000000000000000000000000000006020820152610168565b6102396102dc366004610e23565b610c4a565b6101946102ef366004610dc1565b610ce2565b6101a6610302366004610e23565b5f6020819052908152604090205481565b61025d7f000000000000000000000000cccccccccc33d538dbc2ee4feab0a7a1ff4e8a9481565b6101a6610348366004610e43565b5f92915050565b61025d7f0000000000000000000000000000000005f458fd6ba9eeb5f365d83b7da913dd81565b61025d7f000000000000000000000000c221b7e65ffc80de234bbb6667abdd46593d34f081565b5f73ffffffffffffffffffffffffffffffffffffffff8316610420576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496f754366672f7a65726f2d616464726573730000000000000000000000000060448201526064015b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff84160361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496f754366672f73656c662d61646472657373000000000000000000000000006044820152606401610417565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390527f000000000000000000000000cccccccccc33d538dbc2ee4feab0a7a1ff4e8a9473ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303815f875af1158015610535573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105599190610e74565b506040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018390527f000000000000000000000000cccccccccc33d538dbc2ee4feab0a7a1ff4e8a9473ffffffffffffffffffffffffffffffffffffffff16906342966c68906024015f604051808303815f87803b1580156105df575f5ffd5b505af11580156105f1573d5f5f3e3d5ffd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690527f000000000000000000000000c221b7e65ffc80de234bbb6667abdd46593d34f016925063a9059cbb91506044016020604051808303815f875af1158015610687573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ab9190610e74565b5060019392505050565b335f908152602081905260408120546001146106fd576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000005f458fd6ba9eeb5f365d83b7da913dd73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146107b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496f754366672f696e76616c69642d73656e64657200000000000000000000006044820152606401610417565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152306004820152602481018390527f000000000000000000000000c221b7e65ffc80de234bbb6667abdd46593d34f073ffffffffffffffffffffffffffffffffffffffff16906340c10f19906044015f604051808303815f87803b15801561083d575f5ffd5b505af115801561084f573d5f5f3e3d5ffd5b50506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690527f000000000000000000000000cccccccccc33d538dbc2ee4feab0a7a1ff4e8a941692506340c10f1991506044015f604051808303815f87803b1580156108e0575f5ffd5b505af11580156108f2573d5f5f3e3d5ffd5b50506040518481525f925073ffffffffffffffffffffffffffffffffffffffff871691507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35060019392505050565b5f73ffffffffffffffffffffffffffffffffffffffff83166109cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496f754366672f7a65726f2d61646472657373000000000000000000000000006044820152606401610417565b3073ffffffffffffffffffffffffffffffffffffffff841603610a4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496f754366672f73656c662d61646472657373000000000000000000000000006044820152606401610417565b6040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390527f000000000000000000000000c221b7e65ffc80de234bbb6667abdd46593d34f073ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303815f875af1158015610ae0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b049190610e74565b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490527f000000000000000000000000cccccccccc33d538dbc2ee4feab0a7a1ff4e8a9416906340c10f19906044015f604051808303815f87803b158015610b92575f5ffd5b505af1158015610ba4573d5f5f3e3d5ffd5b5060019695505050505050565b335f90815260208190526040902054600114610bf9576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f90815260208190526040902054600114610c92576040517fea8e4eb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f556e737570706f7274656400000000000000000000000000000000000000000060448201525f90606401610417565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610dbc575f5ffd5b919050565b5f5f60408385031215610dd2575f5ffd5b610ddb83610d99565b946020939093013593505050565b5f5f5f60608486031215610dfb575f5ffd5b610e0484610d99565b9250610e1260208501610d99565b929592945050506040919091013590565b5f60208284031215610e33575f5ffd5b610e3c82610d99565b9392505050565b5f5f60408385031215610e54575f5ffd5b610e5d83610d99565b9150610e6b60208401610d99565b90509250929050565b5f60208284031215610e84575f5ffd5b81518015158114610e3c575f5ffdfea26469706673582212200ea8c721cca1dfc90e8f2d8c7dd0bd7e1f0845e2b10518141411ad4a3ae477df64736f6c634300081c0033

Verified Source Code Partial Match

Compiler: v0.8.28+commit.7893614a EVM: cancun Optimization: Yes (10000 runs)
IouCfg.sol 106 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.28;

import {Auth} from "protocol-v3/misc/Auth.sol";
import {IERC20, IERC20Metadata, IERC20Wrapper} from "protocol-v3/misc/interfaces/IERC20.sol";

interface IERC20Mutate is IERC20 {
    function mint(address account, uint256 amount) external;

    function burn(uint256 amount) external;
}

contract IouCfg is Auth, IERC20, IERC20Metadata, IERC20Wrapper {
    address public immutable escrow;
    address public immutable newCfg;
    address public immutable legacyCfg;
    /// @inheritdoc IERC20Metadata
    uint8 public immutable decimals;

    constructor(address initialWard, address escrow_, address newCfg_, address legacyCfg_) Auth(initialWard) {
        escrow = escrow_;
        newCfg = newCfg_;
        legacyCfg = legacyCfg_;
        decimals = IERC20Metadata(newCfg_).decimals();
    }

    // --- IERC20 Implementation ---
    /// @inheritdoc IERC20
    function totalSupply() external pure returns (uint256) {
        return 0;
    }

    /// @inheritdoc IERC20
    function balanceOf(address) external pure returns (uint256) {
        return 0;
    }

    /// @inheritdoc IERC20
    function transfer(address, uint256) external pure returns (bool) {
        revert("Unsupported");
    }

    /// @inheritdoc IERC20
    function allowance(address, address) external pure returns (uint256) {
        return 0;
    }

    /// @dev A transferFrom function that mints the new CFG tokens and burns the IOU tokens. Only AUTH can call this
    /// function.
    function transferFrom(address sender, address receiver, uint256 amount) external auth returns (bool) {
        // Ensures that only for the direction "Centrifuge to Eth", tokens are minted
        require(sender == escrow, "IouCfg/invalid-sender");

        // Mint wCfg to this contract in order to keep issuance in line and withdrawTo possible
        IERC20Mutate(legacyCfg).mint(address(this), amount);
        IERC20Mutate(newCfg).mint(receiver, amount);

        // IOU is settled and burned
        emit Transfer(sender, address(0), amount);

        return true;
    }

    /// @dev Actually needed in order for this contract to work with the pool manager
    function approve(address, uint256) public virtual returns (bool) {
        return true;
    }

    // --- IERC20Metadata Implementation ---
    /// @inheritdoc IERC20Metadata
    function name() external pure returns (string memory) {
        return "Centrifuge IOU CFG";
    }

    /// @inheritdoc IERC20Metadata
    function symbol() external pure returns (string memory) {
        return "iouCFG";
    }

    // ---- IERC20Wrapper Implementation ----
    /// @dev Compliant to `ERC20Wrapper` contract from OZ for convenience.
    function depositFor(address account, uint256 value) external returns (bool) {
        require(account != address(0), "IouCfg/zero-address");
        require(account != address(this), "IouCfg/self-address");

        IERC20(legacyCfg).transferFrom(msg.sender, address(this), value);
        IERC20Mutate(newCfg).mint(account, value);
        return true;
    }

    /// @dev Compliant to `ERC20Wrapper` contract from OZ for convenience.
    function withdrawTo(address account, uint256 value) external returns (bool) {
        require(account != address(0), "IouCfg/zero-address");
        require(account != address(this), "IouCfg/self-address");

        IERC20Mutate(newCfg).transferFrom(msg.sender, address(this), value);
        IERC20Mutate(newCfg).burn(value);
        IERC20(legacyCfg).transfer(account, value);
        return true;
    }

    /// @dev To ease wrapping via the bundler contract:
    function underlying() external view returns (address) {
        return legacyCfg;
    }
}
Auth.sol 35 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

import {IAuth} from "src/misc/interfaces/IAuth.sol";

/// @title  Auth
/// @notice Simple authentication pattern
/// @author Based on code from https://github.com/makerdao/dss
abstract contract Auth is IAuth {
    /// @inheritdoc IAuth
    mapping(address => uint256) public wards;

    constructor(address initialWard) {
        wards[initialWard] = 1;
        emit Rely(initialWard);
    }

    /// @dev Check if the msg.sender has permissions
    modifier auth() {
        require(wards[msg.sender] == 1, NotAuthorized());
        _;
    }

    /// @inheritdoc IAuth
    function rely(address user) public auth {
        wards[user] = 1;
        emit Rely(user);
    }

    /// @inheritdoc IAuth
    function deny(address user) public auth {
        wards[user] = 0;
        emit Deny(user);
    }
}
IERC20.sol 200 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

/// @title  IERC20
/// @dev    Interface of the ERC20 standard as defined in the EIP.
/// @author Modified from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
interface IERC20 {
    error InvalidAddress();
    error InsufficientBalance();
    error InsufficientAllowance();

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    error PermitExpired();
    error InvalidPermit();

    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

interface IERC20Wrapper {
    /**
     * @dev Returns the address of the underlying ERC-20 token that is being wrapped.
     */
    function underlying() external view returns (address);

    /**
     * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.
     */
    function depositFor(address account, uint256 value) external returns (bool);

    /**
     * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.
     */
    function withdrawTo(address account, uint256 value) external returns (bool);
}
IAuth.sol 18 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;

interface IAuth {
    event Rely(address indexed user);
    event Deny(address indexed user);

    error NotAuthorized();

    /// @notice Returns whether the target is a ward (has admin access)
    function wards(address target) external view returns (uint256);

    /// @notice Make user a ward (give them admin access)
    function rely(address user) external;

    /// @notice Remove user as a ward (remove admin access)
    function deny(address user) external;
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
escrow 0xe2fdcc17 → address
legacyCfg 0xff10ebc6 → address
name 0x06fdde03 → string
newCfg 0xccba5cd8 → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
transfer 0xa9059cbb → bool
underlying 0x6f307dc3 → address
wards 0xbf353dbb → uint256

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

approve 0x095ea7b3
address
uint256
returns: bool
deny 0x9c52a7f1
address user
depositFor 0x2f4f21e2
address account
uint256 value
returns: bool
rely 0x65fae35e
address user
transferFrom 0x23b872dd
address sender
address receiver
uint256 amount
returns: bool
withdrawTo 0x205c2878
address account
uint256 value
returns: bool

Recent Transactions

No transactions found for this address