ETH Price: $2,160.86 (-6.99%)
Gas: 0.16 Gwei

Transaction Decoder

Block:
23660729 at Oct-26-2025 09:26:23 AM +UTC
Transaction Fee:
0.000015830566862896 ETH $0.03
Gas Used:
114,032 Gas / 0.138825653 Gwei

Emitted Events:

435 Uni.Transfer( from=0xD6993E525FAdB23971a20bBb057Af9841eAE076F, to=[Receiver] 0xa69babef1ca67a37ffaf7a485dfff3382056e78c, amount=6523499181370374396 )
436 Dai.Transfer( src=[Receiver] 0xa69babef1ca67a37ffaf7a485dfff3382056e78c, dst=0xD6993E525FAdB23971a20bBb057Af9841eAE076F, wad=41028056519633313525 )
437 0xd6993e525fadb23971a20bbb057af9841eae076f.0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67( 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67, 0x000000000000000000000000a69babef1ca67a37ffaf7a485dfff3382056e78c, 0x000000000000000000000000a69babef1ca67a37ffaf7a485dfff3382056e78c, ffffffffffffffffffffffffffffffffffffffffffffffffa577e00eb9de0704, 0000000000000000000000000000000000000000000000023960f00755649ef5, 00000000000000000000000000000000000000027f4400adeae8618c5c564ffb, 00000000000000000000000000000000000000000000025015d94887b0a6b9ea, 000000000000000000000000000000000000000000000000000000000000477f )

Account State Difference:

  Address   Before After State Difference Code
0x1f9840a8...C4201F984
0x2b728f85...636CA3870
0.923628084317768817 Eth
Nonce: 9987
0.923612253742960675 Eth
Nonce: 9988
0.000015830574808142
0x6B175474...495271d0F
0xA69babEF...82056e78C
(MEV Bot: 0xA69...78C)
104.546374891232447787 Eth104.546373964120134569 Eth0.000000927112313218
0xD6993E52...41eAE076F
(Uniswap V3: UNI-DAI 3)
(BuilderNet)
43.483770553117358889 Eth43.483771480237617353 Eth0.000000927120258464

Execution Trace

ETH 0.000000000007945246 MEV Bot: 0xA69...78C.78e111f6( )
  • ETH 0.000000000007945246 0xc43d99c671a970657e47b4b24402a13235daba99.f4ff5295( )
    • Uniswap V3: UNI-DAI 3.128acb08( )
      • Uni.transfer( dst=0xA69babEF1cA67A37Ffaf7a485DfFF3382056e78C, rawAmount=6523499181370374396 ) => ( True )
      • Dai.balanceOf( 0xD6993E525FAdB23971a20bBb057Af9841eAE076F ) => ( 10045384428840370282163 )
      • MEV Bot: 0xA69...78C.fa461e33( )
        • Dai.transfer( dst=0xD6993E525FAdB23971a20bBb057Af9841eAE076F, wad=41028056519633313525 ) => ( True )
        • Dai.balanceOf( 0xD6993E525FAdB23971a20bBb057Af9841eAE076F ) => ( 10086412485360003595688 )
        • ETH 0.000000927120258464 BuilderNet.CALL( )
          File 1 of 2: Uni
          /**
           *Submitted for verification at Etherscan.io on 2020-09-15
          */
          
          pragma solidity ^0.5.16;
          pragma experimental ABIEncoderV2;
          
          // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
          // Subject to the MIT license.
          
          /**
           * @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 addition of two unsigned integers, reverting with custom message on overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, errorMessage);
          
                  return c;
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               * - Subtraction cannot underflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  return sub(a, b, "SafeMath: subtraction underflow");
              }
          
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               * - Subtraction cannot underflow.
               */
              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 multiplication of two unsigned integers, reverting on overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               * - Multiplication cannot overflow.
               */
              function mul(uint256 a, uint256 b, string memory errorMessage) 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, errorMessage);
          
                  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) {
                  // Solidity only automatically asserts when dividing by 0
                  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;
              }
          }
          
          contract Uni {
              /// @notice EIP-20 token name for this token
              string public constant name = "Uniswap";
          
              /// @notice EIP-20 token symbol for this token
              string public constant symbol = "UNI";
          
              /// @notice EIP-20 token decimals for this token
              uint8 public constant decimals = 18;
          
              /// @notice Total number of tokens in circulation
              uint public totalSupply = 1_000_000_000e18; // 1 billion Uni
          
              /// @notice Address which may mint new tokens
              address public minter;
          
              /// @notice The timestamp after which minting may occur
              uint public mintingAllowedAfter;
          
              /// @notice Minimum time between mints
              uint32 public constant minimumTimeBetweenMints = 1 days * 365;
          
              /// @notice Cap on the percentage of totalSupply that can be minted at each mint
              uint8 public constant mintCap = 2;
          
              /// @notice Allowance amounts on behalf of others
              mapping (address => mapping (address => uint96)) internal allowances;
          
              /// @notice Official record of token balances for each account
              mapping (address => uint96) internal balances;
          
              /// @notice A record of each accounts delegate
              mapping (address => address) public delegates;
          
              /// @notice A checkpoint for marking number of votes from a given block
              struct Checkpoint {
                  uint32 fromBlock;
                  uint96 votes;
              }
          
              /// @notice A record of votes checkpoints for each account, by index
              mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
          
              /// @notice The number of checkpoints for each account
              mapping (address => uint32) public numCheckpoints;
          
              /// @notice The EIP-712 typehash for the contract's domain
              bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
          
              /// @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)");
          
              /// @notice The EIP-712 typehash for the permit struct used by the contract
              bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
          
              /// @notice A record of states for signing / validating signatures
              mapping (address => uint) public nonces;
          
              /// @notice An event thats emitted when the minter address is changed
              event MinterChanged(address minter, address newMinter);
          
              /// @notice An event thats emitted when an account changes its delegate
              event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
          
              /// @notice An event thats emitted when a delegate account's vote balance changes
              event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
          
              /// @notice The standard EIP-20 transfer event
              event Transfer(address indexed from, address indexed to, uint256 amount);
          
              /// @notice The standard EIP-20 approval event
              event Approval(address indexed owner, address indexed spender, uint256 amount);
          
              /**
               * @notice Construct a new Uni token
               * @param account The initial account to grant all the tokens
               * @param minter_ The account with minting ability
               * @param mintingAllowedAfter_ The timestamp after which minting may occur
               */
              constructor(address account, address minter_, uint mintingAllowedAfter_) public {
                  require(mintingAllowedAfter_ >= block.timestamp, "Uni::constructor: minting can only begin after deployment");
          
                  balances[account] = uint96(totalSupply);
                  emit Transfer(address(0), account, totalSupply);
                  minter = minter_;
                  emit MinterChanged(address(0), minter);
                  mintingAllowedAfter = mintingAllowedAfter_;
              }
          
              /**
               * @notice Change the minter address
               * @param minter_ The address of the new minter
               */
              function setMinter(address minter_) external {
                  require(msg.sender == minter, "Uni::setMinter: only the minter can change the minter address");
                  emit MinterChanged(minter, minter_);
                  minter = minter_;
              }
          
              /**
               * @notice Mint new tokens
               * @param dst The address of the destination account
               * @param rawAmount The number of tokens to be minted
               */
              function mint(address dst, uint rawAmount) external {
                  require(msg.sender == minter, "Uni::mint: only the minter can mint");
                  require(block.timestamp >= mintingAllowedAfter, "Uni::mint: minting not allowed yet");
                  require(dst != address(0), "Uni::mint: cannot transfer to the zero address");
          
                  // record the mint
                  mintingAllowedAfter = SafeMath.add(block.timestamp, minimumTimeBetweenMints);
          
                  // mint the amount
                  uint96 amount = safe96(rawAmount, "Uni::mint: amount exceeds 96 bits");
                  require(amount <= SafeMath.div(SafeMath.mul(totalSupply, mintCap), 100), "Uni::mint: exceeded mint cap");
                  totalSupply = safe96(SafeMath.add(totalSupply, amount), "Uni::mint: totalSupply exceeds 96 bits");
          
                  // transfer the amount to the recipient
                  balances[dst] = add96(balances[dst], amount, "Uni::mint: transfer amount overflows");
                  emit Transfer(address(0), dst, amount);
          
                  // move delegates
                  _moveDelegates(address(0), delegates[dst], amount);
              }
          
              /**
               * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`
               * @param account The address of the account holding the funds
               * @param spender The address of the account spending the funds
               * @return The number of tokens approved
               */
              function allowance(address account, address spender) external view returns (uint) {
                  return allowances[account][spender];
              }
          
              /**
               * @notice Approve `spender` to transfer up to `amount` from `src`
               * @dev This will overwrite the approval amount for `spender`
               *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
               * @param spender The address of the account which may transfer tokens
               * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
               * @return Whether or not the approval succeeded
               */
              function approve(address spender, uint rawAmount) external returns (bool) {
                  uint96 amount;
                  if (rawAmount == uint(-1)) {
                      amount = uint96(-1);
                  } else {
                      amount = safe96(rawAmount, "Uni::approve: amount exceeds 96 bits");
                  }
          
                  allowances[msg.sender][spender] = amount;
          
                  emit Approval(msg.sender, spender, amount);
                  return true;
              }
          
              /**
               * @notice Triggers an approval from owner to spends
               * @param owner The address to approve from
               * @param spender The address to be approved
               * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
               * @param deadline The time at which to expire the signature
               * @param v The recovery byte of the signature
               * @param r Half of the ECDSA signature pair
               * @param s Half of the ECDSA signature pair
               */
              function permit(address owner, address spender, uint rawAmount, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
                  uint96 amount;
                  if (rawAmount == uint(-1)) {
                      amount = uint96(-1);
                  } else {
                      amount = safe96(rawAmount, "Uni::permit: amount exceeds 96 bits");
                  }
          
                  bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
                  bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, rawAmount, nonces[owner]++, deadline));
                  bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
                  address signatory = ecrecover(digest, v, r, s);
                  require(signatory != address(0), "Uni::permit: invalid signature");
                  require(signatory == owner, "Uni::permit: unauthorized");
                  require(now <= deadline, "Uni::permit: signature expired");
          
                  allowances[owner][spender] = amount;
          
                  emit Approval(owner, spender, amount);
              }
          
              /**
               * @notice Get the number of tokens held by the `account`
               * @param account The address of the account to get the balance of
               * @return The number of tokens held
               */
              function balanceOf(address account) external view returns (uint) {
                  return balances[account];
              }
          
              /**
               * @notice Transfer `amount` tokens from `msg.sender` to `dst`
               * @param dst The address of the destination account
               * @param rawAmount The number of tokens to transfer
               * @return Whether or not the transfer succeeded
               */
              function transfer(address dst, uint rawAmount) external returns (bool) {
                  uint96 amount = safe96(rawAmount, "Uni::transfer: amount exceeds 96 bits");
                  _transferTokens(msg.sender, dst, amount);
                  return true;
              }
          
              /**
               * @notice Transfer `amount` tokens from `src` to `dst`
               * @param src The address of the source account
               * @param dst The address of the destination account
               * @param rawAmount The number of tokens to transfer
               * @return Whether or not the transfer succeeded
               */
              function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {
                  address spender = msg.sender;
                  uint96 spenderAllowance = allowances[src][spender];
                  uint96 amount = safe96(rawAmount, "Uni::approve: amount exceeds 96 bits");
          
                  if (spender != src && spenderAllowance != uint96(-1)) {
                      uint96 newAllowance = sub96(spenderAllowance, amount, "Uni::transferFrom: transfer amount exceeds spender allowance");
                      allowances[src][spender] = newAllowance;
          
                      emit Approval(src, spender, newAllowance);
                  }
          
                  _transferTokens(src, dst, amount);
                  return true;
              }
          
              /**
               * @notice Delegate votes from `msg.sender` to `delegatee`
               * @param delegatee The address to delegate votes to
               */
              function delegate(address delegatee) public {
                  return _delegate(msg.sender, delegatee);
              }
          
              /**
               * @notice Delegates votes from signatory to `delegatee`
               * @param delegatee The address to delegate votes to
               * @param nonce The contract state required to match the signature
               * @param expiry The time at which to expire the signature
               * @param v The recovery byte of the signature
               * @param r Half of the ECDSA signature pair
               * @param s Half of the ECDSA signature pair
               */
              function delegateBySig(address delegatee, uint nonce, uint 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), "Uni::delegateBySig: invalid signature");
                  require(nonce == nonces[signatory]++, "Uni::delegateBySig: invalid nonce");
                  require(now <= expiry, "Uni::delegateBySig: signature expired");
                  return _delegate(signatory, delegatee);
              }
          
              /**
               * @notice Gets the current votes balance for `account`
               * @param account The address to get votes balance
               * @return The number of current votes for `account`
               */
              function getCurrentVotes(address account) external view returns (uint96) {
                  uint32 nCheckpoints = numCheckpoints[account];
                  return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
              }
          
              /**
               * @notice Determine the prior number of votes for an account as of a block number
               * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
               * @param account The address of the account to check
               * @param blockNumber The block number to get the vote balance at
               * @return The number of votes the account had as of the given block
               */
              function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {
                  require(blockNumber < block.number, "Uni::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) 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), "Uni::_transferTokens: cannot transfer from the zero address");
                  require(dst != address(0), "Uni::_transferTokens: cannot transfer to the zero address");
          
                  balances[src] = sub96(balances[src], amount, "Uni::_transferTokens: transfer amount exceeds balance");
                  balances[dst] = add96(balances[dst], amount, "Uni::_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, "Uni::_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, "Uni::_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, "Uni::_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(uint n, string memory errorMessage) internal pure returns (uint32) {
                  require(n < 2**32, errorMessage);
                  return uint32(n);
              }
          
              function safe96(uint 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 (uint) {
                  uint256 chainId;
                  assembly { chainId := chainid() }
                  return chainId;
              }
          }

          File 2 of 2: Dai
          // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
          pragma solidity =0.5.12;
          
          ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
          // This program is free software: you can redistribute it and/or modify
          // it under the terms of the GNU General Public License as published by
          // the Free Software Foundation, either version 3 of the License, or
          // (at your option) any later version.
          
          // This program is distributed in the hope that it will be useful,
          // but WITHOUT ANY WARRANTY; without even the implied warranty of
          // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          // GNU General Public License for more details.
          
          // You should have received a copy of the GNU General Public License
          // along with this program.  If not, see <http://www.gnu.org/licenses/>.
          
          /* pragma solidity 0.5.12; */
          
          contract LibNote {
              event LogNote(
                  bytes4   indexed  sig,
                  address  indexed  usr,
                  bytes32  indexed  arg1,
                  bytes32  indexed  arg2,
                  bytes             data
              ) anonymous;
          
              modifier note {
                  _;
                  assembly {
                      // log an 'anonymous' event with a constant 6 words of calldata
                      // and four indexed topics: selector, caller, arg1 and arg2
                      let mark := msize                         // end of memory ensures zero
                      mstore(0x40, add(mark, 288))              // update free memory pointer
                      mstore(mark, 0x20)                        // bytes type data offset
                      mstore(add(mark, 0x20), 224)              // bytes size (padded)
                      calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                      log4(mark, 288,                           // calldata
                           shl(224, shr(224, calldataload(0))), // msg.sig
                           caller,                              // msg.sender
                           calldataload(4),                     // arg1
                           calldataload(36)                     // arg2
                          )
                  }
              }
          }
          
          ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
          // Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico
          
          // This program is free software: you can redistribute it and/or modify
          // it under the terms of the GNU Affero General Public License as published by
          // the Free Software Foundation, either version 3 of the License, or
          // (at your option) any later version.
          //
          // This program is distributed in the hope that it will be useful,
          // but WITHOUT ANY WARRANTY; without even the implied warranty of
          // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          // GNU Affero General Public License for more details.
          //
          // You should have received a copy of the GNU Affero General Public License
          // along with this program.  If not, see <https://www.gnu.org/licenses/>.
          
          /* pragma solidity 0.5.12; */
          
          /* import "./lib.sol"; */
          
          contract Dai is LibNote {
              // --- Auth ---
              mapping (address => uint) public wards;
              function rely(address guy) external note auth { wards[guy] = 1; }
              function deny(address guy) external note auth { wards[guy] = 0; }
              modifier auth {
                  require(wards[msg.sender] == 1, "Dai/not-authorized");
                  _;
              }
          
              // --- ERC20 Data ---
              string  public constant name     = "Dai Stablecoin";
              string  public constant symbol   = "DAI";
              string  public constant version  = "1";
              uint8   public constant decimals = 18;
              uint256 public totalSupply;
          
              mapping (address => uint)                      public balanceOf;
              mapping (address => mapping (address => uint)) public allowance;
              mapping (address => uint)                      public nonces;
          
              event Approval(address indexed src, address indexed guy, uint wad);
              event Transfer(address indexed src, address indexed dst, uint wad);
          
              // --- Math ---
              function add(uint x, uint y) internal pure returns (uint z) {
                  require((z = x + y) >= x);
              }
              function sub(uint x, uint y) internal pure returns (uint z) {
                  require((z = x - y) <= x);
              }
          
              // --- EIP712 niceties ---
              bytes32 public DOMAIN_SEPARATOR;
              // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
              bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
          
              constructor(uint256 chainId_) public {
                  wards[msg.sender] = 1;
                  DOMAIN_SEPARATOR = keccak256(abi.encode(
                      keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                      keccak256(bytes(name)),
                      keccak256(bytes(version)),
                      chainId_,
                      address(this)
                  ));
              }
          
              // --- Token ---
              function transfer(address dst, uint wad) external returns (bool) {
                  return transferFrom(msg.sender, dst, wad);
              }
              function transferFrom(address src, address dst, uint wad)
                  public returns (bool)
              {
                  require(balanceOf[src] >= wad, "Dai/insufficient-balance");
                  if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
                      require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance");
                      allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
                  }
                  balanceOf[src] = sub(balanceOf[src], wad);
                  balanceOf[dst] = add(balanceOf[dst], wad);
                  emit Transfer(src, dst, wad);
                  return true;
              }
              function mint(address usr, uint wad) external auth {
                  balanceOf[usr] = add(balanceOf[usr], wad);
                  totalSupply    = add(totalSupply, wad);
                  emit Transfer(address(0), usr, wad);
              }
              function burn(address usr, uint wad) external {
                  require(balanceOf[usr] >= wad, "Dai/insufficient-balance");
                  if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {
                      require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance");
                      allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);
                  }
                  balanceOf[usr] = sub(balanceOf[usr], wad);
                  totalSupply    = sub(totalSupply, wad);
                  emit Transfer(usr, address(0), wad);
              }
              function approve(address usr, uint wad) external returns (bool) {
                  allowance[msg.sender][usr] = wad;
                  emit Approval(msg.sender, usr, wad);
                  return true;
              }
          
              // --- Alias ---
              function push(address usr, uint wad) external {
                  transferFrom(msg.sender, usr, wad);
              }
              function pull(address usr, uint wad) external {
                  transferFrom(usr, msg.sender, wad);
              }
              function move(address src, address dst, uint wad) external {
                  transferFrom(src, dst, wad);
              }
          
              // --- Approve by signature ---
              function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                              bool allowed, uint8 v, bytes32 r, bytes32 s) external
              {
                  bytes32 digest =
                      keccak256(abi.encodePacked(
                          "\x19\x01",
                          DOMAIN_SEPARATOR,
                          keccak256(abi.encode(PERMIT_TYPEHASH,
                                               holder,
                                               spender,
                                               nonce,
                                               expiry,
                                               allowed))
                  ));
          
                  require(holder != address(0), "Dai/invalid-address-0");
                  require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
                  require(expiry == 0 || now <= expiry, "Dai/permit-expired");
                  require(nonce == nonces[holder]++, "Dai/invalid-nonce");
                  uint wad = allowed ? uint(-1) : 0;
                  allowance[holder][spender] = wad;
                  emit Approval(holder, spender, wad);
              }
          }