Transaction Hash:
Block:
20409958 at Jul-29-2024 04:54:47 AM +UTC
Transaction Fee:
0.000048124726021689 ETH
$0.18
Gas Used:
38,399 Gas / 1.253280711 Gwei
Emitted Events:
149 |
MCHCoin.Transfer( from=[Sender] 0xe4eab9999be8d90892951b16242c2dcdfbaa230f, to=0x9763D6413141E23A32d1459fe7CfDe6a4cddCB36, value=20000000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 8.537730308902441269 Eth | 8.537738004600280052 Eth | 0.000007695697838783 | |
0xD69F3065...353c2ECC3 | |||||
0xe4eAb999...dfbaA230f |
0.000054250762145205 Eth
Nonce: 112
|
0.000006126036123516 Eth
Nonce: 113
| 0.000048124726021689 |
Execution Trace
MCHCoin.transfer( recipient=0x9763D6413141E23A32d1459fe7CfDe6a4cddCB36, amount=20000000000000000000 ) => ( True )

-
0xfdcf2339a651e0198f901ed23e2d22f7c2837fa9.738198b4( )
-
0xfdcf2339a651e0198f901ed23e2d22f7c2837fa9.738198b4( )
transfer[ERC20Uint96 (ln:250)]
_transfer[ERC20Uint96 (ln:251)]
_beforeTokenTransfer[ERC20Uint96 (ln:283)]
cast[ERC20Uint96 (ln:285)]
sub[ERC20Uint96 (ln:286)]
add[ERC20Uint96 (ln:287)]
Transfer[ERC20Uint96 (ln:288)]
// Copyright (c) 2018-2020 double jump.tokyo inc. pragma solidity 0.7.4; interface IERC20Permit { function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; } interface IERC20WithPermit { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; } interface ICompGovernance { function delegate(address delegatee) external; function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external; function getCurrentVotes(address account) external view returns (uint96); function getPriorVotes(address account, uint blockNumber) external view returns (uint96); event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); } interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } interface IERC20Optionals { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); } library Uint96 { function cast(uint256 a) public pure returns (uint96) { require(a < 2**96); return uint96(a); } function add(uint96 a, uint96 b) internal pure returns (uint96) { uint96 c = a + b; require(c >= a, "addition overflow"); return c; } function sub(uint96 a, uint96 b) internal pure returns (uint96) { require(a >= b, "subtraction overflow"); return a - b; } function mul(uint96 a, uint96 b) internal pure returns (uint96) { if (a == 0) { return 0; } uint96 c = a * b; require(c / a == b, "multiplication overflow"); return c; } function div(uint96 a, uint96 b) internal pure returns (uint96) { require(b != 0, "division by 0"); return a / b; } function mod(uint96 a, uint96 b) internal pure returns (uint96) { require(b != 0, "modulo by 0"); return a % b; } function toString(uint96 a) internal pure returns (string memory) { bytes32 retBytes32; uint96 len = 0; if (a == 0) { retBytes32 = "0"; len++; } else { uint96 value = a; while (value > 0) { retBytes32 = bytes32(uint256(retBytes32) / (2 ** 8)); retBytes32 |= bytes32(((value % 10) + 48) * 2 ** (8 * 31)); value /= 10; len++; } } bytes memory ret = new bytes(len); uint96 i; for (i = 0; i < len; i++) { ret[i] = retBytes32[i]; } return string(ret); } } contract EIP712 { bytes32 private constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); bytes32 public DOMAIN_SEPARATOR; mapping (address => uint) private _nonces; constructor(string memory name, string memory version) { uint chainId = getChainId(); DOMAIN_SEPARATOR = keccak256( abi.encode( DOMAIN_TYPEHASH, keccak256(bytes(name)), keccak256(bytes(version)), chainId, address(this) ) ); } function getChainId() private pure returns (uint) { uint chainId; assembly { chainId := chainid() } return chainId; } function nonces(address account) public view returns (uint) { return _nonces[account]; } function incrementNonce(address account) public returns (uint) { return _nonces[account]++; } function getDigest(bytes32 structHash) public view returns (bytes32) { return keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR, structHash ) ); } function recover(bytes32 digest, uint8 v, bytes32 r, bytes32 s) public pure returns (address) { address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0), "ERC712: invalid signature"); return recoveredAddress; } } library Roles { struct Role { mapping (address => bool) bearer; } function add(Role storage role, address account) internal { require(!has(role, account), "role already has the account"); role.bearer[account] = true; } function remove(Role storage role, address account) internal { require(has(role, account), "role dosen't have the account"); role.bearer[account] = false; } function has(Role storage role, address account) internal view returns (bool) { return role.bearer[account]; } } contract Mintable { using Roles for Roles.Role; event MinterAdded(address indexed account); event MinterRemoved(address indexed account); Roles.Role private _minters; constructor() { _minters.add(msg.sender); } modifier onlyMinter() { require(_minters.has(msg.sender), "Must be minter"); _; } function isMinter(address account) public view returns (bool) { return _minters.has(account); } function addMinter(address account) public onlyMinter() { _minters.add(account); emit MinterAdded(account); } function removeMinter(address account) public onlyMinter() { _minters.remove(account); emit MinterRemoved(account); } } abstract contract ERC20Uint96 is IERC20, IERC20Optionals { using Uint96 for uint96; mapping (address => uint96) private _balances; mapping (address => mapping (address => uint96)) private _allowances; uint96 private _totalSupply; uint96 private _cap = 2**96-1; string private _name; string private _symbol; uint8 private _decimals; constructor (string memory tokenName, string memory tokenSymbol, uint96 tokenCap) { require(tokenCap > 0, "ERC20Capped: cap is 0"); _name = tokenName; _symbol = tokenSymbol; _decimals = 18; _cap = tokenCap; } function cap() public view returns (uint256) { return _cap; } function totalSupply() public view override virtual returns (uint256) { return _totalSupply; } function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } function transfer(address recipient, uint256 amount) external override returns (bool) { _transfer(msg.sender, recipient, amount); return true; } function allowance(address owner, address spender) public view override returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 amount) external override returns (bool) { _approve(msg.sender, spender, amount); return true; } function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); uint96 _amount = Uint96.cast(amount); _allowances[owner][spender] = _amount; emit Approval(owner, spender, amount); } function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(Uint96.cast(amount))); return true; } function _transfer(address sender, address recipient, uint amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint96 _amount = Uint96.cast(amount); _balances[sender] = _balances[sender].sub(_amount); _balances[recipient] = _balances[recipient].add(_amount); emit Transfer(sender, recipient, amount); } function _beforeTokenTransfer(address sender, address recipient, uint256 amount) internal virtual {} function _mint(address account, uint amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); uint96 _amount = Uint96.cast(amount); _totalSupply = _totalSupply.add(_amount); require(_totalSupply <= _cap, "ERC20Capped: cap exceeded"); _balances[account] = _balances[account].add(_amount); emit Transfer(address(0), account, _amount); } function _burn(address account, uint amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint96 _amount = Uint96.cast(amount); _totalSupply = _totalSupply.sub(_amount); _balances[account] = _balances[account].sub(_amount); emit Transfer(account, address(0), _amount); } function name() public view override returns (string memory) { return _name; } function symbol() external view override returns (string memory) { return _symbol; } function decimals() external view override returns (uint8) { return _decimals; } } abstract contract ERC20Uint96Governance is EIP712, ERC20Uint96, ICompGovernance { using Uint96 for uint96; struct Checkpoint { uint32 fromBlock; uint96 votes; } /// @notice The EIP-712 typehash for the delegation struct used by the contract bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); mapping (address => address) public delegates; mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; mapping (address => uint32) public numCheckpoints; constructor() { } function _beforeTokenTransfer(address sender, address recipient, uint256 amount) internal override { _moveDelegates(delegates[sender], delegates[recipient], Uint96.cast(amount)); super._beforeTokenTransfer(sender, recipient, amount); } function delegate(address delegatee) public override { return _delegate(msg.sender, delegatee); } function delegateBySig(address delegatee, uint nonce, uint deadline, uint8 v, bytes32 r, bytes32 s) public override { require(block.timestamp <= deadline, "ERC20Governance: signature expired"); bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, deadline)); bytes32 digest = getDigest(structHash); address signatory = recover(digest, v, r, s); require(nonce == incrementNonce(delegatee), "ERC20Governance: invalid nonce"); return _delegate(signatory, delegatee); } function getCurrentVotes(address account) external view override returns (uint96) { uint32 nCheckpoints = numCheckpoints[account]; return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; } function getPriorVotes(address account, uint blockNumber) public view override returns (uint96) { require(blockNumber < block.number, "Comp::getPriorVotes: not yet determined"); uint32 nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } // First check most recent balance if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { return checkpoints[account][nCheckpoints - 1].votes; } // Next check implicit zero balance if (checkpoints[account][0].fromBlock > blockNumber) { return 0; } uint32 lower = 0; uint32 upper = nCheckpoints - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow Checkpoint memory cp = checkpoints[account][center]; if (cp.fromBlock == blockNumber) { return cp.votes; } else if (cp.fromBlock < blockNumber) { lower = center; } else { upper = center - 1; } } return checkpoints[account][lower].votes; } function _delegate(address delegator, address delegatee) private { address currentDelegate = delegates[delegator]; uint96 delegatorBalance = _balanceOf(delegator); delegates[delegator] = delegatee; emit DelegateChanged(delegator, currentDelegate, delegatee); _moveDelegates(currentDelegate, delegatee, delegatorBalance); } function _moveDelegates(address srcRep, address dstRep, uint96 amount) private { if (srcRep != dstRep && amount > 0) { if (srcRep != address(0)) { uint32 srcRepNum = numCheckpoints[srcRep]; uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; uint96 srcRepNew = srcRepOld.sub(amount); _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); } if (dstRep != address(0)) { uint32 dstRepNum = numCheckpoints[dstRep]; uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; uint96 dstRepNew = dstRepOld.add(amount); _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); } } } function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) private { require(block.number < 2**32, "ERC20Governance: block number exceeds 32 bits"); uint32 blockNumber = uint32(block.number); if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; } else { checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); numCheckpoints[delegatee] = nCheckpoints + 1; } emit DelegateVotesChanged(delegatee, oldVotes, newVotes); } function _balanceOf(address account) private view returns (uint96) { return Uint96.cast(super.balanceOf(account)); } } contract MCHCoin is ERC20Uint96Governance, IERC20Permit, Mintable { using Uint96 for uint96; // 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); constructor() ERC20Uint96("MCHCoin","MCHC", 50000000 * 10**18) EIP712("MCHCoin","1") { } uint256 public offchainIssued; function setOffchainIssued(uint256 _new) external onlyMinter { offchainIssued = _new; } function onchainIssued() external view returns (uint256) { return super.totalSupply(); } function totalSupply() public override view returns (uint256) { if (offchainIssued != 0) { return offchainIssued; } return super.totalSupply(); } function mintTo(address account, uint amount) external onlyMinter returns (bool) { _mint(account, amount); return true; } function burn(uint amount) external returns (bool) { _burn(msg.sender, amount); return true; } function burnFrom(address account, uint amount) external returns (bool) { uint96 allowance = Uint96.cast(allowance(account, msg.sender)); uint256 decreasedAllowance = allowance.sub(Uint96.cast(amount)); _approve(account, msg.sender, decreasedAllowance); _burn(account, amount); return true; } function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external override { require(deadline >= block.timestamp, 'ERC20Permit: EXPIRED'); bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, incrementNonce(owner), deadline)); bytes32 digest = getDigest(structHash); address recoveredAddress = recover(digest, v, r, s); require(recoveredAddress == owner, 'ERC20Permit: INVALID_SIGNATURE'); _approve(owner, spender, value); } }