Transaction Hash:
Block:
16498549 at Jan-27-2023 01:48:35 PM +UTC
Transaction Fee:
0.00077668453423593 ETH
$2.00
Gas Used:
46,665 Gas / 16.643834442 Gwei
Emitted Events:
286 |
SingDao.Approval( owner=[Sender] 0x3e38d907bb48cb13567a2f13fb5d4a6a02e0537a, spender=0xfB85B9Ec...5132120D0, amount=79228162514264337593543950335 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x3E38d907...a02E0537a |
0.025596777399503795 Eth
Nonce: 2
|
0.024820092865267865 Eth
Nonce: 3
| 0.00077668453423593 | ||
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 225.627480170070784243 Eth | 225.627550167570784243 Eth | 0.0000699975 | |
0x993864E4...a635B875F |
Execution Trace
SingDao.approve( spender=0xfB85B9Ec50560e302Ab106F1E2857d95132120D0, rawAmount=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
approve[SingDao (ln:146)]
safe96[SingDao (ln:151)]
Approval[SingDao (ln:154)]
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; address public nominatedOwner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event OwnerNominated(address indexed newOwner); event OwnerChanged(address indexed oldOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, 'You must be nominated before you can accept ownership'); emit OwnerChanged(_owner, nominatedOwner); _owner = nominatedOwner; nominatedOwner = address(0); } }// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "./Ownable.sol"; contract SingDao is Ownable { /// @notice EIP-20 token name for this token string public constant name = "Singularity Dao"; /// @notice EIP-20 token symbol for this token string public constant symbol = "SDAO"; /// @notice EIP-20 token decimals for this token uint8 public constant decimals = 18; /// @notice Total number of tokens in circulation uint256 public totalSupply = 100_000_000e18; ILocker public locker; mapping(address => mapping(address => uint96)) internal allowances; mapping(address => uint96) internal balances; mapping(address => address) public delegates; struct Checkpoint { uint32 fromBlock; uint96 votes; } mapping(address => mapping(uint32 => Checkpoint)) public checkpoints; mapping(address => uint32) public numCheckpoints; bytes32 public constant DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,uint256 chainId,address verifyingContract)" ); bytes32 public constant DELEGATION_TYPEHASH = keccak256( "Delegation(address delegatee,uint256 nonce,uint256 expiry)" ); mapping(address => uint256) public nonces; event DelegateChanged( address indexed delegator, address indexed fromDelegate, address indexed toDelegate ); event DelegateVotesChanged( address indexed delegate, uint256 previousBalance, uint256 newBalance ); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval( address indexed owner, address indexed spender, uint256 amount ); constructor(address account) public { balances[account] = uint96(totalSupply); emit Transfer(address(0), account, totalSupply); } function mint(address dst, uint rawAmount) external onlyOwner { // mint the amount require( dst != address(0), "Sdao::_transferTokens: cannot mint to the zero address" ); uint96 amount = safe96(rawAmount, "Sdao::mint: amount exceeds 96 bits"); totalSupply = safe96(SafeMath.add(totalSupply, amount), "Sdao::mint: totalSupply exceeds 96 bits"); // transfer the amount to the recipient balances[dst] = add96(balances[dst], amount, "Sdao::mint: transfer amount overflows"); emit Transfer(address(0), dst, amount); // move delegates _moveDelegates(address(0), delegates[dst], amount); } function allowance(address account, address spender) external view returns (uint256) { return allowances[account][spender]; } function approve(address spender, uint256 rawAmount) external returns (bool) { uint96 amount; if (rawAmount == uint256(-1)) { amount = uint96(-1); } else { amount = safe96(rawAmount, "SDAO::approve: amount exceeds 96 bits"); } allowances[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function balanceOf(address account) external view returns (uint256) { return balances[account]; } function nonceOf(address account) external view returns (uint256) { return nonces[account]; } function transfer(address dst, uint256 rawAmount) external returns (bool) { uint96 amount = safe96(rawAmount, "SDAO::transfer: amount exceeds 96 bits"); _transferTokens(msg.sender, dst, amount); return true; } function transferFrom( address src, address dst, uint256 rawAmount ) external returns (bool) { address spender = msg.sender; uint96 spenderAllowance = allowances[src][spender]; uint96 amount = safe96(rawAmount, "SDAO::approve: amount exceeds 96 bits"); if (spender != src && spenderAllowance != uint96(-1)) { uint96 newAllowance = sub96( spenderAllowance, amount, "SDAO::transferFrom: transfer amount exceeds spender allowance" ); allowances[src][spender] = newAllowance; emit Approval(src, spender, newAllowance); } _transferTokens(src, dst, amount); return true; } function delegate(address delegatee) public { return _delegate(msg.sender, delegatee); } function delegateBySig( address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) public { bytes32 domainSeparator = keccak256( abi.encode( DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this) ) ); bytes32 structHash = keccak256( abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry) ); bytes32 digest = keccak256( abi.encodePacked("\\x19\\x01", domainSeparator, structHash) ); address signatory = ecrecover(digest, v, r, s); require(signatory != address(0), "sdao::delegateBySig: invalid signature"); require(nonce == nonces[signatory]++, "sdao::delegateBySig: invalid nonce"); require(now <= expiry, "sdao::delegateBySig: signature expired"); return _delegate(signatory, delegatee); } function getCurrentVotes(address account) external view returns (uint96) { uint32 nCheckpoints = numCheckpoints[account]; return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; } function getPriorVotes(address account, uint256 blockNumber) public view returns (uint96) { require( blockNumber < block.number, "sdao::getPriorVotes: not yet determined" ); uint32 nCheckpoints = numCheckpoints[account]; if (nCheckpoints == 0) { return 0; } if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { return checkpoints[account][nCheckpoints - 1].votes; } if (checkpoints[account][0].fromBlock > blockNumber) { return 0; } uint32 lower = 0; uint32 upper = nCheckpoints - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2; 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) internal { address currentDelegate = delegates[delegator]; uint96 delegatorBalance = balances[delegator]; delegates[delegator] = delegatee; emit DelegateChanged(delegator, currentDelegate, delegatee); _moveDelegates(currentDelegate, delegatee, delegatorBalance); } function _transferTokens( address src, address dst, uint96 amount ) internal { require( src != address(0), "sdao::_transferTokens: cannot transfer from the zero address" ); require( dst != address(0), "sdao::_transferTokens: cannot transfer to the zero address" ); if(address(locker) != address(0)){ locker.lockOrGetPenalty(src,dst); } balances[src] = sub96( balances[src], amount, "sdao::_transferTokens: transfer amount exceeds balance" ); balances[dst] = add96( balances[dst], amount, "sdao::_transferTokens: transfer amount overflows" ); emit Transfer(src, dst, amount); _moveDelegates(delegates[src], delegates[dst], amount); } function _moveDelegates( address srcRep, address dstRep, uint96 amount ) internal { 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 = sub96( srcRepOld, amount, "sdao::_moveVotes: vote amount underflows" ); _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 = add96( dstRepOld, amount, "sdao::_moveVotes: vote amount overflows" ); _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); } } } function _writeCheckpoint( address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes ) internal { uint32 blockNumber = safe32( block.number, "sdao::_writeCheckpoint: block number exceeds 32 bits" ); 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 safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) { require(n < 2**32, errorMessage); return uint32(n); } function safe96(uint256 n, string memory errorMessage) internal pure returns (uint96) { require(n < 2**96, errorMessage); return uint96(n); } function add96( uint96 a, uint96 b, string memory errorMessage ) internal pure returns (uint96) { uint96 c = a + b; require(c >= a, errorMessage); return c; } function sub96( uint96 a, uint96 b, string memory errorMessage ) internal pure returns (uint96) { require(b <= a, errorMessage); return a - b; } function getChainId() internal pure returns (uint256) { uint256 chainId; assembly { chainId := chainid() } return chainId; } function setLocker(address _locker) external onlyOwner { locker = ILocker(_locker); } } interface ILocker { function lockOrGetPenalty(address source, address dest)external returns(bool,uint256); } // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }