Transaction Hash:
Block:
22544003 at May-23-2025 07:12:59 AM +UTC
Transaction Fee:
0.000069304 ETH
$0.18
Gas Used:
34,652 Gas / 2 Gwei
Emitted Events:
420 |
MapleTokenProxy.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000006fd4ba7973a0d39a91734bbc35bc2bcaa99e3b0, 0x00000000000000000000000028c6c06298d514db089934071355e5743bf21d60, 0000000000000000000000000000000000000000000002fc888d2e20033d0c00 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x06FD4bA7...Caa99E3B0 | (Binance Dep: 0x06FD4bA7973a0d39a91734bbc35bC2bCaa99E3B0) |
0.012186646916599684 Eth
Nonce: 113458
|
0.012117342916599684 Eth
Nonce: 113459
| 0.000069304 | |
0x643C4E15...A3Ef52d66 | |||||
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 18.11032697546947992 Eth | 18.110355232870069776 Eth | 0.000028257400589856 |
Execution Trace
MapleTokenProxy.a9059cbb( )
-
MapleToken.transfer( recipient_=0x28C6c06298d514Db089934071355E5743bf21d60, amount_=14103152043790000000000 ) => ( success_=True )
transfer[ERC20Proxied (ln:134)]
_transfer[ERC20Proxied (ln:135)]
Transfer[ERC20Proxied (ln:185)]
File 1 of 2: MapleTokenProxy
File 2 of 2: MapleToken
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { IMapleTokenInitializerLike, IGlobalsLike } from "./interfaces/Interfaces.sol"; import { IMapleTokenProxy } from "./interfaces/IMapleTokenProxy.sol"; contract MapleTokenProxy is IMapleTokenProxy { bytes32 internal constant GLOBALS_SLOT = bytes32(uint256(keccak256("eip1967.proxy.globals")) - 1); bytes32 internal constant IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); constructor(address globals_, address implementation_, address initializer_, address tokenMigrator_) { _setAddress(GLOBALS_SLOT, globals_); _setAddress(IMPLEMENTATION_SLOT, implementation_); ( bool success_, ) = initializer_.delegatecall(abi.encodeWithSelector( IMapleTokenInitializerLike(initializer_).initialize.selector, tokenMigrator_, IGlobalsLike(globals_).mapleTreasury() )); require(success_, "MTP:INIT_FAILED"); } /**************************************************************************************************************************************/ /*** Overridden Functions ***/ /**************************************************************************************************************************************/ function setImplementation(address newImplementation_) override external { IGlobalsLike globals_ = IGlobalsLike(_globals()); require(msg.sender == globals_.governor(), "MTP:SI:NOT_GOVERNOR"); bool isScheduledCall_ = globals_.isValidScheduledCall(msg.sender, address(this), "MTP:SET_IMPLEMENTATION", msg.data); require(isScheduledCall_, "MTP:SI:NOT_SCHEDULED"); globals_.unscheduleCall(msg.sender, "MTP:SET_IMPLEMENTATION", msg.data); _setAddress(IMPLEMENTATION_SLOT, newImplementation_); emit ImplementationSet(newImplementation_); } /**************************************************************************************************************************************/ /*** View Functions ***/ /**************************************************************************************************************************************/ function _globals() internal view returns (address globals_) { globals_ = _getAddress(GLOBALS_SLOT); } function _implementation() internal view returns (address implementation_) { implementation_ = _getAddress(IMPLEMENTATION_SLOT); } /**************************************************************************************************************************************/ /*** Utility Functions ***/ /**************************************************************************************************************************************/ function _setAddress(bytes32 slot_, address value_) internal { assembly { sstore(slot_, value_) } } function _getAddress(bytes32 slot_) internal view returns (address value_) { assembly { value_ := sload(slot_) } } /**************************************************************************************************************************************/ /*** Fallback Function ***/ /**************************************************************************************************************************************/ fallback() external { address implementation_ = _implementation(); require(implementation_.code.length != 0, "MTP:F:NO_CODE_ON_IMPLEMENTATION"); assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), implementation_, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } } // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; interface IERC20Like { function burn(address from, uint256 value) external; function mint(address to, uint256 value) external; function totalSupply() external view returns (uint256 totalSupply); } interface IGlobalsLike { function governor() external view returns (address governor); function isInstanceOf(bytes32 instanceKey, address instance) external view returns (bool isInstance); function isValidScheduledCall( address caller, address target, bytes32 functionId, bytes calldata callData ) external view returns (bool isValidScheduledCall); function mapleTreasury() external view returns (address mapleTreasury); function unscheduleCall(address caller, bytes32 functionId, bytes calldata callData) external; } interface IMapleTokenInitializerLike { function initialize(address migrator, address treasury) external; } interface IMapleTokenLike is IERC20Like { function globals() external view returns (address globals); } // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; interface IMapleTokenProxy { /** * @dev Emitted when the implementation address is set. * @param implementation The address of the new implementation. */ event ImplementationSet(address indexed implementation); /** * @dev Sets the implementation address. * @param newImplementation The address to set the implementation to. */ function setImplementation(address newImplementation) external; }
File 2 of 2: MapleToken
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { ERC20Proxied } from "../modules/erc20/contracts/ERC20Proxied.sol"; import { IGlobalsLike } from "./interfaces/Interfaces.sol"; import { IMapleToken } from "./interfaces/IMapleToken.sol"; contract MapleToken is IMapleToken, ERC20Proxied { bytes32 internal constant GLOBALS_SLOT = bytes32(uint256(keccak256("eip1967.proxy.globals")) - 1); bytes32 internal constant IMPLEMENTATION_SLOT = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1); mapping(address => bool) public isModule; modifier onlyGovernor { require(msg.sender == governor(), "MT:NOT_GOVERNOR"); _; } modifier onlyScheduled(bytes32 functionId_) { IGlobalsLike globals_ = IGlobalsLike(globals()); bool isScheduledCall_ = globals_.isValidScheduledCall(msg.sender, address(this), functionId_, msg.data); require(isScheduledCall_, "MT:NOT_SCHEDULED"); globals_.unscheduleCall(msg.sender, functionId_, msg.data); _; } /**************************************************************************************************************************************/ /*** External Functions ***/ /**************************************************************************************************************************************/ function addModule(address module_) external onlyGovernor onlyScheduled("MT:ADD_MODULE") { isModule[module_] = true; emit ModuleAdded(module_); } function removeModule(address module_) external onlyGovernor onlyScheduled("MT:REMOVE_MODULE") { delete isModule[module_]; emit ModuleRemoved(module_); } function burn(address from_, uint256 amount_) external { require(isModule[msg.sender], "MT:B:NOT_MODULE"); _burn(from_, amount_); emit Burn(from_, amount_); } function mint(address to_, uint256 amount_) external { require(isModule[msg.sender], "MT:M:NOT_MODULE"); _mint(to_, amount_); emit Mint(to_, amount_); } /**************************************************************************************************************************************/ /*** View Functions ***/ /**************************************************************************************************************************************/ function implementation() external view returns (address implementation_) { implementation_ = _getAddress(IMPLEMENTATION_SLOT); } function governor() public view returns (address governor_) { governor_ = IGlobalsLike(globals()).governor(); } function globals() public view returns (address globals_) { globals_ = _getAddress(GLOBALS_SLOT); } /**************************************************************************************************************************************/ /*** Utility Functions ***/ /**************************************************************************************************************************************/ function _getAddress(bytes32 slot_) internal view returns (address value_) { assembly { value_ := sload(slot_) } } } // SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; import { IERC20 } from "./interfaces/IERC20.sol"; /* ███████╗██████╗ ██████╗ ██████╗ ██████╗ ██╔════╝██╔══██╗██╔════╝ ╚════██╗██╔═████╗ █████╗ ██████╔╝██║ █████╔╝██║██╔██║ ██╔══╝ ██╔══██╗██║ ██╔═══╝ ████╔╝██║ ███████╗██║ ██║╚██████╗ ███████╗╚██████╔╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═════╝ */ /** * @title Modern ERC-20 implementation. * @dev Acknowledgements to Solmate, OpenZeppelin, and DSS for inspiring this code. */ abstract contract ERC20Proxied is IERC20 { /**************************************************************************************************************************************/ /*** ERC-20 ***/ /**************************************************************************************************************************************/ string public override name; string public override symbol; uint8 public override decimals; uint256 public override totalSupply; mapping(address => uint256) public override balanceOf; mapping(address => mapping(address => uint256)) public override allowance; /**************************************************************************************************************************************/ /*** ERC-2612 ***/ /**************************************************************************************************************************************/ // PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint256) public override nonces; /**************************************************************************************************************************************/ /*** External Functions ***/ /**************************************************************************************************************************************/ function approve(address spender_, uint256 amount_) public virtual override returns (bool success_) { _approve(msg.sender, spender_, amount_); return true; } function decreaseAllowance(address spender_, uint256 subtractedAmount_) public virtual override returns (bool success_) { _decreaseAllowance(msg.sender, spender_, subtractedAmount_); return true; } function increaseAllowance(address spender_, uint256 addedAmount_) public virtual override returns (bool success_) { _approve(msg.sender, spender_, allowance[msg.sender][spender_] + addedAmount_); return true; } function permit(address owner_, address spender_, uint256 amount_, uint256 deadline_, uint8 v_, bytes32 r_, bytes32 s_) public virtual override { require(deadline_ >= block.timestamp, "ERC20:P:EXPIRED"); // Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. require( uint256(s_) <= uint256(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) && (v_ == 27 || v_ == 28), "ERC20:P:MALLEABLE" ); // Nonce realistically cannot overflow. unchecked { bytes32 digest_ = keccak256( abi.encodePacked( "\\x19\\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, owner_, spender_, amount_, nonces[owner_]++, deadline_)) ) ); address recoveredAddress_ = ecrecover(digest_, v_, r_, s_); require(recoveredAddress_ == owner_ && owner_ != address(0), "ERC20:P:INVALID_SIGNATURE"); } _approve(owner_, spender_, amount_); } function transfer(address recipient_, uint256 amount_) public virtual override returns (bool success_) { _transfer(msg.sender, recipient_, amount_); return true; } function transferFrom(address owner_, address recipient_, uint256 amount_) public virtual override returns (bool success_) { _decreaseAllowance(owner_, msg.sender, amount_); _transfer(owner_, recipient_, amount_); return true; } /**************************************************************************************************************************************/ /*** View Functions ***/ /**************************************************************************************************************************************/ function DOMAIN_SEPARATOR() public view override returns (bytes32 domainSeparator_) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256(bytes("1")), block.chainid, address(this) ) ); } /**************************************************************************************************************************************/ /*** Internal Functions ***/ /**************************************************************************************************************************************/ function _approve(address owner_, address spender_, uint256 amount_) internal { emit Approval(owner_, spender_, allowance[owner_][spender_] = amount_); } function _burn(address owner_, uint256 amount_) internal { balanceOf[owner_] -= amount_; // Cannot underflow because a user's balance will never be larger than the total supply. unchecked { totalSupply -= amount_; } emit Transfer(owner_, address(0), amount_); } function _decreaseAllowance(address owner_, address spender_, uint256 subtractedAmount_) internal { uint256 spenderAllowance = allowance[owner_][spender_]; // Cache to memory. if (spenderAllowance != type(uint256).max) { _approve(owner_, spender_, spenderAllowance - subtractedAmount_); } } function _mint(address recipient_, uint256 amount_) internal { totalSupply += amount_; // Cannot overflow because totalSupply would first overflow in the statement above. unchecked { balanceOf[recipient_] += amount_; } emit Transfer(address(0), recipient_, amount_); } function _transfer(address owner_, address recipient_, uint256 amount_) internal { balanceOf[owner_] -= amount_; // Cannot overflow because minting prevents overflow of totalSupply, and sum of user balances == totalSupply. unchecked { balanceOf[recipient_] += amount_; } emit Transfer(owner_, recipient_, amount_); } } // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; interface IERC20Like { function burn(address from, uint256 value) external; function mint(address to, uint256 value) external; function totalSupply() external view returns (uint256 totalSupply); } interface IGlobalsLike { function governor() external view returns (address governor); function isInstanceOf(bytes32 instanceKey, address instance) external view returns (bool isInstance); function isValidScheduledCall( address caller, address target, bytes32 functionId, bytes calldata callData ) external view returns (bool isValidScheduledCall); function mapleTreasury() external view returns (address mapleTreasury); function unscheduleCall(address caller, bytes32 functionId, bytes calldata callData) external; } interface IMapleTokenInitializerLike { function initialize(address migrator, address treasury) external; } interface IMapleTokenLike is IERC20Like { function globals() external view returns (address globals); } // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.18; import { IERC20 } from "../../modules/erc20/contracts/interfaces/IERC20.sol"; interface IMapleToken is IERC20 { /**************************************************************************************************************************************/ /*** Events ***/ /**************************************************************************************************************************************/ /** * @dev A burn was performed. * @param from The address of the account whose tokens were burned. * @param amount The amount of tokens that were burned. */ event Burn(address indexed from, uint256 amount); /** * @dev A mint was performed. * @param to The address of the account whose tokens were minted. * @param amount The amount of tokens that were minted. */ event Mint(address indexed to, uint256 amount); /** * @dev A new module was added to the MapleToken. * @param module The address the module added. */ event ModuleAdded(address indexed module); /** * @dev A module was removed from the MapleToken. * @param module The address the module removed. */ event ModuleRemoved(address indexed module); /**************************************************************************************************************************************/ /*** Functions ***/ /**************************************************************************************************************************************/ /** * @dev Adds a new module to the MapleToken. * @param module The address the module to add. */ function addModule(address module) external; /** * @dev Burns a specified amount of tokens from the an account. * @param from The address to burn tokens from. * @param amount The amount of tokens to burn. */ function burn(address from, uint256 amount) external; /** * @dev Returns the address of the Maple Governor. * @return governor The address of the Maple Governor. */ function governor() external view returns (address governor); /** * @dev Returns the address of the Maple Globals contract. * @return globals The address of the Maple Globals contract. */ function globals() external view returns (address globals); /** * @dev Returns the proxy's implementation address. * @return implementation_ The address of the implementation. */ function implementation() external view returns (address implementation_); /** * @dev Returns true if the specified module is a burner. * @param module The address of the module to check. * @return isModule True if the address is a valid module. */ function isModule(address module) external view returns (bool isModule); /** * @dev Mints a specified amount of tokens to an account. * @param to The address to mint tokens to. * @param amount The amount of tokens to mint. */ function mint(address to, uint256 amount) external; /** * @dev Removes a module from the MapleToken. * @param module The address the module to remove. */ function removeModule(address module) external; } // SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.7; /// @title Interface of the ERC20 standard as defined in the EIP, including EIP-2612 permit functionality. interface IERC20 { /**************************************************************************************************************************************/ /*** Events ***/ /**************************************************************************************************************************************/ /** * @dev Emitted when one account has set the allowance of another account over their tokens. * @param owner_ Account that tokens are approved from. * @param spender_ Account that tokens are approved for. * @param amount_ Amount of tokens that have been approved. */ event Approval(address indexed owner_, address indexed spender_, uint256 amount_); /** * @dev Emitted when tokens have moved from one account to another. * @param owner_ Account that tokens have moved from. * @param recipient_ Account that tokens have moved to. * @param amount_ Amount of tokens that have been transferred. */ event Transfer(address indexed owner_, address indexed recipient_, uint256 amount_); /**************************************************************************************************************************************/ /*** External Functions ***/ /**************************************************************************************************************************************/ /** * @dev Function that allows one account to set the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param amount_ Amount of tokens that have been approved. * @return success_ Boolean indicating whether the operation succeeded. */ function approve(address spender_, uint256 amount_) external returns (bool success_); /** * @dev Function that allows one account to decrease the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param subtractedAmount_ Amount to decrease approval by. * @return success_ Boolean indicating whether the operation succeeded. */ function decreaseAllowance(address spender_, uint256 subtractedAmount_) external returns (bool success_); /** * @dev Function that allows one account to increase the allowance of another account over their tokens. * Emits an {Approval} event. * @param spender_ Account that tokens are approved for. * @param addedAmount_ Amount to increase approval by. * @return success_ Boolean indicating whether the operation succeeded. */ function increaseAllowance(address spender_, uint256 addedAmount_) external returns (bool success_); /** * @dev Approve by signature. * @param owner_ Owner address that signed the permit. * @param spender_ Spender of the permit. * @param amount_ Permit approval spend limit. * @param deadline_ Deadline after which the permit is invalid. * @param v_ ECDSA signature v component. * @param r_ ECDSA signature r component. * @param s_ ECDSA signature s component. */ function permit(address owner_, address spender_, uint amount_, uint deadline_, uint8 v_, bytes32 r_, bytes32 s_) external; /** * @dev Moves an amount of tokens from `msg.sender` to a specified account. * Emits a {Transfer} event. * @param recipient_ Account that receives tokens. * @param amount_ Amount of tokens that are transferred. * @return success_ Boolean indicating whether the operation succeeded. */ function transfer(address recipient_, uint256 amount_) external returns (bool success_); /** * @dev Moves a pre-approved amount of tokens from a sender to a specified account. * Emits a {Transfer} event. * Emits an {Approval} event. * @param owner_ Account that tokens are moving from. * @param recipient_ Account that receives tokens. * @param amount_ Amount of tokens that are transferred. * @return success_ Boolean indicating whether the operation succeeded. */ function transferFrom(address owner_, address recipient_, uint256 amount_) external returns (bool success_); /**************************************************************************************************************************************/ /*** View Functions ***/ /**************************************************************************************************************************************/ /** * @dev Returns the allowance that one account has given another over their tokens. * @param owner_ Account that tokens are approved from. * @param spender_ Account that tokens are approved for. * @return allowance_ Allowance that one account has given another over their tokens. */ function allowance(address owner_, address spender_) external view returns (uint256 allowance_); /** * @dev Returns the amount of tokens owned by a given account. * @param account_ Account that owns the tokens. * @return balance_ Amount of tokens owned by a given account. */ function balanceOf(address account_) external view returns (uint256 balance_); /** * @dev Returns the decimal precision used by the token. * @return decimals_ The decimal precision used by the token. */ function decimals() external view returns (uint8 decimals_); /** * @dev Returns the signature domain separator. * @return domainSeparator_ The signature domain separator. */ function DOMAIN_SEPARATOR() external view returns (bytes32 domainSeparator_); /** * @dev Returns the name of the token. * @return name_ The name of the token. */ function name() external view returns (string memory name_); /** * @dev Returns the nonce for the given owner. * @param owner_ The address of the owner account. * @return nonce_ The nonce for the given owner. */ function nonces(address owner_) external view returns (uint256 nonce_); /** * @dev Returns the permit type hash. * @return permitTypehash_ The permit type hash. */ function PERMIT_TYPEHASH() external view returns (bytes32 permitTypehash_); /** * @dev Returns the symbol of the token. * @return symbol_ The symbol of the token. */ function symbol() external view returns (string memory symbol_); /** * @dev Returns the total amount of tokens in existence. * @return totalSupply_ The total amount of tokens in existence. */ function totalSupply() external view returns (uint256 totalSupply_); }