Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xaAfdfA4a935d8511bF285af11A0544ce7e4a1199
Balance 17.6594 ETH
Nonce 1
Code Size 3681 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3681 bytes
0x6080604052600436106100855760003560e01c8063a389783e11610059578063a389783e14610134578063b7f64bd514610192578063e3d670d7146101e4578063e81f02b614610223578063ff05280e1461024357600080fd5b80629315b91461008a5780633ccfd60b146100ac5780635ecb16cd146100c15780639a375b07146100e1575b600080fd5b34801561009657600080fd5b506100aa6100a5366004610bed565b610256565b005b3480156100b857600080fd5b506100aa610309565b3480156100cd57600080fd5b506100aa6100dc366004610c7f565b610319565b3480156100ed57600080fd5b506100aa6100fc366004610c49565b3360009081526001602090815260408083206001600160a01b0395909516835293905291909120805460ff1916911515919091179055565b34801561014057600080fd5b5061017d61014f366004610bbb565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205460ff1690565b60405190151581526020015b60405180910390f35b34801561019e57600080fd5b506101d66101ad366004610bbb565b6001600160a01b0391821660009081526020818152604080832093909416825291909152205490565b604051908152602001610189565b3480156101f057600080fd5b506101d66101ff366004610b9a565b6001600160a01b031660009081526020818152604080832083805290915290205490565b34801561022f57600080fd5b506100aa61023e366004610bbb565b610362565b6100aa610251366004610cf8565b6103cf565b6001600160a01b038316331480159061029557506001600160a01b0380841660009081526001602090815260408083209386168352929052205460ff16155b156102b3576040516393256b7d60e01b815260040160405180910390fd5b60005b8151811015610303576102f184848484815181106102e457634e487b7160e01b600052603260045260246000fd5b60200260200101516108c7565b806102fb81610dd6565b9150506102b6565b50505050565b33610316818060006108c7565b50565b3360005b825181101561035d5761034b82838584815181106102e457634e487b7160e01b600052603260045260246000fd5b8061035581610dd6565b91505061031d565b505050565b6001600160a01b03821633148015906103a157506001600160a01b0380831660009081526001602090815260408083209385168352929052205460ff16155b156103bf576040516393256b7d60e01b815260040160405180910390fd5b6103cb828260006108c7565b5050565b8281146103ef5760405163251f56a160e21b815260040160405180910390fd5b6000805b828110156104525783838281811061041b57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906104309190610cd6565b61043e9061ffff1683610d7f565b91508061044a81610dd6565b9150506103f3565b50806127101461047557604051632429608560e11b815260040160405180910390fd5b6001600160a01b03861661064d573460005b858110156106465760008585838181106104b157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906104c69190610cd6565b61ffff1611156106345760006127108686848181106104f557634e487b7160e01b600052603260045260246000fd5b905060200201602081019061050a9190610cd6565b6105189061ffff1685610db7565b6105229190610d97565b9050806000808a8a8681811061054857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061055d9190610b9a565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546105af9190610d7f565b9091555088905087838181106105d557634e487b7160e01b600052603260045260246000fd5b90506020020160208101906105ea9190610b9a565b604080516001600160a01b038c811682526020820185905292909216917f55f368ec5df1aca853572d5a6cbda215a84cf17a93c765932dcfb1c237df2eca910160405180910390a2505b8061063e81610dd6565b915050610487565b50506108be565b6040516323b872dd60e01b81523360048201523060248201526044810188905286906000906001600160a01b038316906323b872dd90606401602060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d89190610cba565b9050806106f8576040516312171d8360e31b815260040160405180910390fd5b60005b868110156108ba57600086868381811061072557634e487b7160e01b600052603260045260246000fd5b905060200201602081019061073a9190610cd6565b61ffff1611156108a857600061271087878481811061076957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061077e9190610cd6565b61078c9061ffff168d610db7565b6107969190610d97565b9050806000808b8b868181106107bc57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906107d19190610b9a565b6001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008282546108239190610d7f565b90915550899050888381811061084957634e487b7160e01b600052603260045260246000fd5b905060200201602081019061085e9190610b9a565b604080516001600160a01b038d811682526020820185905292909216917f55f368ec5df1aca853572d5a6cbda215a84cf17a93c765932dcfb1c237df2eca910160405180910390a2505b806108b281610dd6565b9150506106fb565b5050505b50505050505050565b6001600160a01b03838116600090815260208181526040808320938516835292905290812080549190558061090f576040516321cd723f60e21b815260040160405180910390fd5b6001600160a01b038216610999576000836001600160a01b03168260405160006040518083038185875af1925050503d806000811461096a576040519150601f19603f3d011682016040523d82523d6000602084013e61096f565b606091505b50508091505080610993576040516312171d8360e31b815260040160405180910390fd5b50610a43565b60405163a9059cbb60e01b81526001600160a01b03848116600483015260248201839052839160009183169063a9059cbb90604401602060405180830381600087803b1580156109e857600080fd5b505af11580156109fc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a209190610cba565b905080610a40576040516312171d8360e31b815260040160405180910390fd5b50505b604080516001600160a01b038481168252602082018490528616917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a250505050565b80356001600160a01b0381168114610aa657600080fd5b919050565b60008083601f840112610abc578081fd5b50813567ffffffffffffffff811115610ad3578182fd5b6020830191508360208260051b8501011115610aee57600080fd5b9250929050565b600082601f830112610b05578081fd5b8135602067ffffffffffffffff80831115610b2257610b22610e07565b8260051b604051601f19603f83011681018181108482111715610b4757610b47610e07565b60405284815283810192508684018288018501891015610b65578687fd5b8692505b85831015610b8e57610b7a81610a8f565b845292840192600192909201918401610b69565b50979650505050505050565b600060208284031215610bab578081fd5b610bb482610a8f565b9392505050565b60008060408385031215610bcd578081fd5b610bd683610a8f565b9150610be460208401610a8f565b90509250929050565b600080600060608486031215610c01578081fd5b610c0a84610a8f565b9250610c1860208501610a8f565b9150604084013567ffffffffffffffff811115610c33578182fd5b610c3f86828701610af5565b9150509250925092565b60008060408385031215610c5b578182fd5b610c6483610a8f565b91506020830135610c7481610e1d565b809150509250929050565b600060208284031215610c90578081fd5b813567ffffffffffffffff811115610ca6578182fd5b610cb284828501610af5565b949350505050565b600060208284031215610ccb578081fd5b8151610bb481610e1d565b600060208284031215610ce7578081fd5b813561ffff81168114610bb4578182fd5b60008060008060008060808789031215610d10578182fd5b86359550610d2060208801610a8f565b9450604087013567ffffffffffffffff80821115610d3c578384fd5b610d488a838b01610aab565b90965094506060890135915080821115610d60578384fd5b50610d6d89828a01610aab565b979a9699509497509295939492505050565b60008219821115610d9257610d92610df1565b500190565b600082610db257634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615610dd157610dd1610df1565b500290565b6000600019821415610dea57610dea610df1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461031657600080fdfea26469706673582212205352862ca256ca68d1afa1d275e255472b33ccc2c38c04d1a884345b5048abb864736f6c63430008040033

Verified Source Code Full Match

Compiler: v0.8.4+commit.c7e474f2 EVM: istanbul Optimization: Yes (200 runs)
ArchetypePayouts.sol 157 lines
// SPDX-License-Identifier: MIT
// ArchetypePayouts v0.7.0
//
//        d8888                 888               888
//       d88888                 888               888
//      d88P888                 888               888
//     d88P 888 888d888 .d8888b 88888b.   .d88b.  888888 888  888 88888b.   .d88b.
//    d88P  888 888P"  d88P"    888 "88b d8P  Y8b 888    888  888 888 "88b d8P  Y8b
//   d88P   888 888    888      888  888 88888888 888    888  888 888  888 88888888
//  d8888888888 888    Y88b.    888  888 Y8b.     Y88b.  Y88b 888 888 d88P Y8b.
// d88P     888 888     "Y8888P 888  888  "Y8888   "Y888  "Y88888 88888P"   "Y8888
//                                                            888 888
//                                                       Y8b d88P 888
//

pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

error InvalidLength();
error InvalidSplitShares();
error TransferFailed();
error BalanceEmpty();
error NotApprovedToWithdraw();

contract ArchetypePayouts {
  event Withdrawal(address indexed src, address token, uint256 wad);
  event FundsAdded(address indexed recipient, address token, uint256 amount);

  mapping(address => mapping(address => uint256)) private _balance;
  mapping(address => mapping(address => bool)) private _approvals;

  function updateBalances(
    uint256 totalAmount,
    address token,
    address[] calldata recipients,
    uint16[] calldata splits
  ) public payable {
    if (recipients.length != splits.length) {
      revert InvalidLength();
    }

    uint256 totalShares = 0;
    for (uint256 i = 0; i < splits.length; i++) {
      totalShares += splits[i];
    }
    if (totalShares != 10000) {
      revert InvalidSplitShares();
    }

    if (token == address(0)) {
      // ETH payments
      uint256 totalReceived = msg.value;
      for (uint256 i = 0; i < recipients.length; i++) {
        if (splits[i] > 0) {
          uint256 amountToAdd = (totalReceived * splits[i]) / 10000;
          _balance[recipients[i]][token] += amountToAdd;
          emit FundsAdded(recipients[i], token, amountToAdd);
        }
      }
    } else {
      // ERC20 payments
      IERC20 paymentToken = IERC20(token);
      bool success = paymentToken.transferFrom(msg.sender, address(this), totalAmount);
      if (!success) {
        revert TransferFailed();
      }

      for (uint256 i = 0; i < recipients.length; i++) {
        if (splits[i] > 0) {
          uint256 amountToAdd = (totalAmount * splits[i]) / 10000;
          _balance[recipients[i]][token] += amountToAdd;
          emit FundsAdded(recipients[i], token, amountToAdd);
        }
      }
    }
  }

  function withdraw() external {
    address msgSender = msg.sender;
    _withdraw(msgSender, msgSender, address(0));
  }

  function withdrawTokens(address[] memory tokens) external {
    address msgSender = msg.sender;

    for (uint256 i = 0; i < tokens.length; i++) {
      _withdraw(msgSender, msgSender, tokens[i]);
    }
  }

  function withdrawFrom(address from, address to) public {
    if (from != msg.sender && !_approvals[from][to]) {
      revert NotApprovedToWithdraw();
    }
    _withdraw(from, to, address(0));
  }

  function withdrawTokensFrom(
    address from,
    address to,
    address[] memory tokens
  ) public {
    if (from != msg.sender && !_approvals[from][to]) {
      revert NotApprovedToWithdraw();
    }
    for (uint256 i = 0; i < tokens.length; i++) {
      _withdraw(from, to, tokens[i]);
    }
  }

  function _withdraw(
    address from,
    address to,
    address token
  ) internal {
    uint256 wad;

    wad = _balance[from][token];
    _balance[from][token] = 0;

    if (wad == 0) {
      revert BalanceEmpty();
    }

    if (token == address(0)) {
      bool success = false;
      (success, ) = to.call{ value: wad }("");
      if (!success) {
        revert TransferFailed();
      }
    } else {
      IERC20 erc20Token = IERC20(token);
      bool success = erc20Token.transfer(to, wad);
      if (!success) {
        revert TransferFailed();
      }
    }
    emit Withdrawal(from, token, wad);
  }

  function approveWithdrawal(address delegate, bool approved) external {
    _approvals[msg.sender][delegate] = approved;
  }

  function isApproved(address from, address delegate) external view returns (bool) {
    return _approvals[from][delegate];
  }

  function balance(address recipient) external view returns (uint256) {
    return _balance[recipient][address(0)];
  }

  function balanceToken(address recipient, address token) external view returns (uint256) {
    return _balance[recipient][token];
  }
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

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

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

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

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

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

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

Read Contract

balance 0xe3d670d7 → uint256
balanceToken 0xb7f64bd5 → uint256
isApproved 0xa389783e → bool

Write Contract 6 functions

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

approveWithdrawal 0x9a375b07
address delegate
bool approved
updateBalances 0xff05280e
uint256 totalAmount
address token
address[] recipients
uint16[] splits
withdraw 0x3ccfd60b
No parameters
withdrawFrom 0xe81f02b6
address from
address to
withdrawTokens 0x5ecb16cd
address[] tokens
withdrawTokensFrom 0x009315b9
address from
address to
address[] tokens

Recent Transactions

No transactions found for this address