Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 17867627 | 965 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Minimal Proxy Contract for 0xfece55912861a401738604c52998604ba45115a1
Contract Name:
OneinchV5Authorizer
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "DEXBaseACL.sol";
import "ACLUtils.sol";
interface IPool {
function token0() external view returns (address);
function token1() external view returns (address);
}
contract OneinchV5Authorizer is DEXBaseACL {
bytes32 public constant NAME = "1inchV5Authorizer";
uint256 public constant VERSION = 1;
// For 1inch aggreator data.
uint256 private constant _REVERSE_MASK = 0x8000000000000000000000000000000000000000000000000000000000000000;
uint256 private constant _ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
uint256 private constant _WETH_MASK = 0x4000000000000000000000000000000000000000000000000000000000000000; // For unoswap
uint256 private constant _ONE_FOR_ZERO_MASK = 1 << 255;
uint256 private constant _WETH_UNWRAP_MASK = 1 << 253; // For uniswapV3Swap.
uint256 private constant _UNWRAP_WETH_FLAG = 1 << 252; // For fillOrderRFQ
address public constant ROUTER = 0x1111111254EEB25477B68fb85Ed929f73A960582;
address public immutable WETH = getWrappedTokenAddress();
constructor(address _owner, address _caller) DEXBaseACL(_owner, _caller) {}
function contracts() public view override returns (address[] memory _contracts) {
_contracts = new address[](1);
_contracts[0] = ROUTER;
}
function _getToken(address _token) internal view returns (address) {
return _token == ZERO_ADDRESS ? ETH_ADDRESS : _token;
}
// Checking functions.
struct SwapDescription {
address srcToken;
address dstToken;
address srcReceiver;
address dstReceiver;
uint256 amount;
uint256 minReturnAmount;
uint256 flags;
}
function swap(address, SwapDescription calldata _desc, bytes calldata, bytes calldata) external view {
_checkRecipient(_desc.dstReceiver);
address srcToken = _getToken(_desc.srcToken);
address dstToken = _getToken(_desc.dstToken);
_swapInOutTokenCheck(srcToken, dstToken);
}
//already restrict recipient must be msg.sender in 1inch contract
function unoswap(address _srcToken, uint256, uint256, uint256[] calldata pools) external view {
uint256 lastPool = pools[pools.length - 1];
IPool lastPair = IPool(address(uint160(lastPool & _ADDRESS_MASK)));
address srcToken = _getToken(_srcToken);
bool isReversed = lastPool & _REVERSE_MASK == 0;
bool unwrapWeth = lastPool & _WETH_MASK > 0;
address dstToken = isReversed ? lastPair.token1() : lastPair.token0();
if (unwrapWeth) {
require(dstToken == WETH, "Dst not WETH");
dstToken = ETH_ADDRESS;
}
_swapInOutTokenCheck(srcToken, dstToken);
}
function uniswapV3Swap(uint256 amount, uint256 minReturn, uint256[] calldata pools) external view {
uint256 lastPoolUint = pools[pools.length - 1];
uint256 firstPoolUint = pools[0];
IPool firstPool = IPool(address(uint160(firstPoolUint)));
IPool lastPool = IPool(address(uint160(lastPoolUint)));
bool zeroForOneFirstPool = firstPoolUint & _ONE_FOR_ZERO_MASK == 0;
bool zeroForOneLastPool = lastPoolUint & _ONE_FOR_ZERO_MASK == 0;
address srcToken = zeroForOneFirstPool ? firstPool.token0() : firstPool.token1();
address dstToken = zeroForOneLastPool ? lastPool.token1() : lastPool.token0();
bool wrapWeth = _txn().value > 0;
bool unwrapWeth = lastPoolUint & _WETH_UNWRAP_MASK > 0;
if (wrapWeth) {
require(srcToken == WETH, "Src not WETH");
srcToken = ETH_ADDRESS;
}
if (unwrapWeth) {
require(dstToken == WETH, "Dst not WETH");
dstToken = ETH_ADDRESS;
}
_swapInOutTokenCheck(_getToken(srcToken), _getToken(dstToken));
}
// Safe is the taker.
struct Order {
uint256 salt;
address makerAsset; // For safe to buy
address takerAsset; // For safe to sell
address maker;
address receiver; // Where to send takerAsset, default zero means sending to maker.
address allowedSender; // equals to Zero address on public orders
uint256 makingAmount;
uint256 takingAmount;
uint256 offsets;
bytes interactions; // concat(makerAssetData, takerAssetData, getMakingAmount, getTakingAmount, predicate, permit, preIntercation, postInteraction)
}
function fillOrder(
Order calldata order,
bytes calldata signature,
bytes calldata interaction,
uint256 makingAmount,
uint256 takingAmount,
uint256 skipPermitAndThresholdAmount
) external view {
address srcToken = order.takerAsset;
address dstToken = order.makerAsset;
_swapInOutTokenCheck(_getToken(srcToken), _getToken(dstToken));
}
struct OrderRFQ {
uint256 info; // lowest 64 bits is the order id, next 64 bits is the expiration timestamp
address makerAsset;
address takerAsset;
address maker;
address allowedSender; // equals to Zero address on public orders
uint256 makingAmount;
uint256 takingAmount;
}
function _checkRFQOrder(OrderRFQ calldata order, uint256 flagsAndAmount) internal view {
address srcToken = order.takerAsset;
address dstToken = order.makerAsset;
if (srcToken == WETH && _txn().value > 0) {
srcToken = ETH_ADDRESS;
}
if (dstToken == WETH && flagsAndAmount & _UNWRAP_WETH_FLAG != 0) {
dstToken = ETH_ADDRESS;
}
_swapInOutTokenCheck(_getToken(srcToken), _getToken(dstToken));
}
function fillOrderRFQ(OrderRFQ calldata order, bytes calldata signature, uint256 flagsAndAmount) external view {
_checkRFQOrder(order, flagsAndAmount);
}
function fillOrderRFQCompact(OrderRFQ calldata order, bytes32 r, bytes32 vs, uint256 flagsAndAmount) external view {
_checkRFQOrder(order, flagsAndAmount);
}
function clipperSwap(
address clipperExchange,
address srcToken,
address dstToken,
uint256 inputAmount,
uint256 outputAmount,
uint256 goodUntil,
bytes32 r,
bytes32 vs
) external view {
_swapInOutTokenCheck(_getToken(srcToken), _getToken(dstToken));
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "EnumerableSet.sol";
import "BaseACL.sol";
/// @title DEXBaseACL - ACL template for DEX.
/// @author Cobo Safe Dev Team https://www.cobo.com/
abstract contract DEXBaseACL is BaseACL {
using EnumerableSet for EnumerableSet.AddressSet;
bytes32 public constant override TYPE = AuthType.DEX;
EnumerableSet.AddressSet swapInTokenWhitelist;
EnumerableSet.AddressSet swapOutTokenWhitelist;
event SwapInTokenAdded(address indexed token);
event SwapInTokenRemoved(address indexed token);
event SwapOutTokenAdded(address indexed token);
event SwapOutTokenRemoved(address indexed token);
struct SwapInToken {
address token;
bool tokenStatus;
}
struct SwapOutToken {
address token;
bool tokenStatus;
}
constructor(address _owner, address _caller) BaseACL(_owner, _caller) {}
// External set functions.
function addSwapInTokens(address[] calldata _tokens) external onlyOwner {
for (uint256 i = 0; i < _tokens.length; i++) {
address token = _tokens[i];
if (swapInTokenWhitelist.add(token)) {
emit SwapInTokenAdded(token);
}
}
}
function removeSwapInTokens(address[] calldata _tokens) external onlyOwner {
for (uint256 i = 0; i < _tokens.length; i++) {
address token = _tokens[i];
if (swapInTokenWhitelist.remove(token)) {
emit SwapInTokenRemoved(token);
}
}
}
function addSwapOutTokens(address[] calldata _tokens) external onlyOwner {
for (uint256 i = 0; i < _tokens.length; i++) {
address token = _tokens[i];
if (swapOutTokenWhitelist.add(token)) {
emit SwapOutTokenAdded(token);
}
}
}
function removeSwapOutTokens(address[] calldata _tokens) external onlyOwner {
for (uint256 i = 0; i < _tokens.length; i++) {
address token = _tokens[i];
if (swapOutTokenWhitelist.remove(token)) {
emit SwapOutTokenRemoved(token);
}
}
}
// External view functions.
function hasSwapInToken(address _token) public view returns (bool) {
return swapInTokenWhitelist.contains(_token);
}
function getSwapInTokens() external view returns (address[] memory tokens) {
return swapInTokenWhitelist.values();
}
function hasSwapOutToken(address _token) public view returns (bool) {
return swapOutTokenWhitelist.contains(_token);
}
function getSwapOutTokens() external view returns (address[] memory tokens) {
return swapOutTokenWhitelist.values();
}
// Internal check utility functions.
function _swapInTokenCheck(address _token) internal view {
require(hasSwapInToken(_token), "In token not allowed");
}
function _swapOutTokenCheck(address _token) internal view {
require(hasSwapOutToken(_token), "Out token not allowed");
}
function _swapInOutTokenCheck(address _inToken, address _outToken) internal view {
_swapInTokenCheck(_inToken);
_swapOutTokenCheck(_outToken);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "EnumerableSet.sol";
import "BaseAuthorizer.sol";
/// @title BaseACL - Basic ACL template which uses the call-self trick to perform function and parameters check.
/// @author Cobo Safe Dev Team https://www.cobo.com/
/// @dev Steps to extend this:
/// 1. Set the NAME and VERSION.
/// 2. Write ACL functions according the target contract.
/// 3. Add a constructor. eg:
/// `constructor(address _owner, address _caller) BaseACL(_owner, _caller) {}`
/// 4. Override `contracts()` to only target contracts that you checks. For txn
//// whose to address is not in the list `_preExecCheck()` will revert.
/// 5. (Optional) If state changing operation in the checking method is required,
/// override `_preExecCheck()` to change `staticcall` to `call`.
/// 6. (Optional) Override `permissions()` to summary your checking methods.
///
/// NOTE for ACL developers:
/// 1. Implement your checking functions which should be defined extractly the same as
/// the target method to control so you do not bother to write a lot abi.decode code.
/// 2. Checking funtions should NOT return any value, use `require` to perform your check.
/// 3. BaseACL may serve for multiple target contracts.
/// - Implement contracts() to manage the target contracts set.
/// - Use `onlyContract` modifier or check `_txn().to` in checking functions.
/// 4. Do NOT implement your own `setXXX` function, wrap your data into `Variant` and
/// use `setVariant` `getVariant` instead.
/// 5. If you still need your own setter, ensure `onlyOwner` is used.
abstract contract BaseACL is BaseAuthorizer {
using EnumerableSet for EnumerableSet.Bytes32Set;
/// @dev Set such constants in sub contract.
// bytes32 public constant NAME = "BaseACL";
// bytes32 public constant override TYPE = "ACLType";
// uint256 public constant VERSION = 0;
/// Only preExecCheck is used in BaseACL.
uint256 public constant flag = AuthFlags.HAS_PRE_CHECK_MASK;
constructor(address _owner, address _caller) BaseAuthorizer(_owner, _caller) {}
/// Internal functions.
function _parseReturnData(
bool success,
bytes memory revertData
) internal pure returns (AuthorizerReturnData memory authData) {
if (success) {
// ACL check function should return empty bytes which differs from normal view functions.
require(revertData.length == 0, Errors.ACL_FUNC_RETURNS_NON_EMPTY);
authData.result = AuthResult.SUCCESS;
} else {
if (revertData.length < 68) {
// 4(Error sig) + 32(offset) + 32(length)
authData.message = string(revertData);
} else {
assembly {
// Slice the sighash.
revertData := add(revertData, 0x04)
}
authData.message = abi.decode(revertData, (string));
}
}
}
function _contractCheck(TransactionData calldata transaction) internal virtual returns (bool result) {
// This works as a catch-all check. Sample but safer.
address to = transaction.to;
address[] memory _contracts = contracts(); // Call external.
for (uint i = 0; i < _contracts.length; i++) {
if (to == _contracts[i]) return true;
}
return false;
}
function _packTxn(TransactionData calldata transaction) internal pure virtual returns (bytes memory) {
bytes memory txnData = abi.encode(transaction);
bytes memory callDataSize = abi.encode(transaction.data.length);
return abi.encodePacked(transaction.data, txnData, callDataSize);
}
function _unpackTxn() internal pure virtual returns (TransactionData memory transaction) {
uint256 end = msg.data.length;
uint256 callDataSize = abi.decode(msg.data[end - 32:end], (uint256));
transaction = abi.decode(msg.data[callDataSize:], (TransactionData));
}
// @dev Only valid in self-call checking functions.
function _txn() internal pure virtual returns (TransactionData memory transaction) {
return _unpackTxn();
}
function _preExecCheck(
TransactionData calldata transaction
) internal virtual override returns (AuthorizerReturnData memory authData) {
if (!_contractCheck(transaction)) {
authData.result = AuthResult.FAILED;
authData.message = Errors.NOT_IN_CONTRACT_LIST;
return authData;
}
(bool success, bytes memory revertData) = address(this).staticcall(_packTxn(transaction));
return _parseReturnData(success, revertData);
}
function _postExecCheck(
TransactionData calldata transaction,
TransactionResult calldata callResult,
AuthorizerReturnData calldata preData
) internal virtual override returns (AuthorizerReturnData memory authData) {
authData.result = AuthResult.SUCCESS;
}
// Internal view functions.
// Utilities for checking functions.
function _checkRecipient(address _recipient) internal view {
require(_recipient == _txn().from, "Invalid recipient");
}
function _checkContract(address _contract) internal view {
require(_contract == _txn().to, "Invalid contract");
}
// Modifiers.
modifier onlyContract(address _contract) {
_checkContract(_contract);
_;
}
/// External functions
/// @dev Implement your own access control checking functions here.
// example:
// function transfer(address to, uint256 amount)
// onlyContract(USDT_ADDR)
// external view
// {
// require(amount > 0 & amount < 10000, "amount not in range");
// }
/// @dev Override this as `_preExecCheck` used.
/// @notice Target contracts this BaseACL controls.
function contracts() public view virtual returns (address[] memory _contracts) {}
fallback() external virtual {
revert(Errors.METHOD_NOT_ALLOW);
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "BaseOwnable.sol";
import "Errors.sol";
import "IAuthorizer.sol";
import "IAccount.sol";
import "IRoleManager.sol";
/// @title BaseAuthorizer - A basic pausable authorizer with caller restriction.
/// @author Cobo Safe Dev Team https://www.cobo.com/
/// @dev Base contract to extend to implement specific authorizer.
abstract contract BaseAuthorizer is IAuthorizer, BaseOwnable {
/// @dev Override such constants while extending BaseAuthorizer.
bool public paused = false;
// Often used for off-chain system.
// Each contract instance has its own value.
bytes32 public tag = "";
// The caller which is able to call this contract's pre/postExecProcess
// and pre/postExecCheck having side-effect.
// It is usually the account or the parent authorizer(set) on higher level.
address public caller;
// This is the account this authorizer works for.
// Currently used to lookup `roleManager`.
// If not used it is OK to keep it unset.
address public account;
event CallerSet(address indexed caller);
event AccountSet(address indexed account);
event TagSet(bytes32 indexed tag);
event PausedSet(bool indexed status);
constructor(address _owner, address _caller) BaseOwnable(_owner) {
caller = _caller;
}
function initialize(address _owner, address _caller) public {
initialize(_owner);
caller = _caller;
emit CallerSet(_caller);
}
function initialize(address _owner, address _caller, address _account) public {
initialize(_owner, _caller);
account = _account;
emit AccountSet(_account);
}
modifier onlyCaller() virtual {
require(msg.sender == caller, Errors.INVALID_CALLER);
_;
}
/// @notice Change the caller.
/// @param _caller the caller which calls the authorizer.
function setCaller(address _caller) external onlyOwner {
caller = _caller;
emit CallerSet(_caller);
}
/// @notice Change the account.
/// @param _account the account which the authorizer get role manager from.
function setAccount(address _account) external onlyOwner {
account = _account;
emit AccountSet(_account);
}
/// @notice Change the tag for the contract instance.
/// @dev For off-chain index.
/// @param _tag the tag
function setTag(bytes32 _tag) external onlyOwner {
tag = _tag;
emit TagSet(_tag);
}
/// @notice Set the pause status. Authorizer just denies all when paused.
/// @param _paused the paused status: true or false.
function setPaused(bool _paused) external onlyOwner {
paused = _paused;
emit PausedSet(_paused);
}
/// @notice Function check if a transaction can be executed.
/// @param transaction Transaction data which contains from,to,value,data,delegate
/// @return authData Return check status, error message and hint (if needed)
function preExecCheck(
TransactionData calldata transaction
) external virtual onlyCaller returns (AuthorizerReturnData memory authData) {
if (paused) {
authData.result = AuthResult.FAILED;
authData.message = Errors.AUTHORIZER_PAUSED;
} else {
authData = _preExecCheck(transaction);
}
}
/// @notice Check after transaction execution.
/// @param transaction Transaction data which contains from,to,value,data,delegate
/// @param callResult Transaction call status and return data.
function postExecCheck(
TransactionData calldata transaction,
TransactionResult calldata callResult,
AuthorizerReturnData calldata preData
) external virtual onlyCaller returns (AuthorizerReturnData memory authData) {
if (paused) {
authData.result = AuthResult.FAILED;
authData.message = Errors.AUTHORIZER_PAUSED;
} else {
authData = _postExecCheck(transaction, callResult, preData);
}
}
/// @dev Perform actions before the transaction execution.
/// `onlyCaller` check forced here or attacker can call this directly
/// to pollute our data.
function preExecProcess(TransactionData calldata transaction) external virtual onlyCaller {
if (!paused) _preExecProcess(transaction);
}
/// @dev Perform actions after the transaction execution.
/// `onlyCaller` check forced here or attacker can call this directly
/// to pollute our data.
function postExecProcess(
TransactionData calldata transaction,
TransactionResult calldata callResult
) external virtual onlyCaller {
if (!paused) _postExecProcess(transaction, callResult);
}
/// @dev Extract the roles of the delegate. If no roleManager set return empty lists.
function _authenticate(TransactionData calldata transaction) internal view returns (bytes32[] memory roles) {
return _authenticate(transaction.delegate);
}
function _authenticate(address delegate) internal view returns (bytes32[] memory roles) {
require(account != address(0), Errors.ACCOUNT_NOT_SET);
address roleManager = IAccount(account).roleManager();
require(roleManager != address(0), Errors.ROLE_MANAGER_NOT_SET);
roles = IRoleManager(roleManager).getRoles(delegate);
}
/// @dev Call `roleManager` to validate the role of delegate.
function _hasRole(TransactionData calldata transaction, bytes32 role) internal view returns (bool) {
return _hasRole(transaction.delegate, role);
}
function _hasRole(address delegate, bytes32 role) internal view returns (bool) {
require(account != address(0), Errors.ACCOUNT_NOT_SET);
address roleManager = IAccount(account).roleManager();
require(roleManager != address(0), Errors.ROLE_MANAGER_NOT_SET);
return IRoleManager(roleManager).hasRole(delegate, role);
}
/// @dev Override this to implement new authorization.
/// NOTE: If your check involves side-effect, onlyCaller should be used.
function _preExecCheck(
TransactionData calldata transaction
) internal virtual returns (AuthorizerReturnData memory authData) {}
/// @dev Override this to implement new authorization.
function _postExecCheck(
TransactionData calldata transaction,
TransactionResult calldata callResult,
AuthorizerReturnData calldata preData
) internal virtual returns (AuthorizerReturnData memory) {}
function _preExecProcess(TransactionData calldata transaction) internal virtual {}
function _postExecProcess(
TransactionData calldata transaction,
TransactionResult calldata callResult
) internal virtual {}
/// @dev Override this if you implement new type of authorizer.
function TYPE() external view virtual returns (bytes32) {
return AuthType.COMMON;
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "Errors.sol";
import "BaseVersion.sol";
/// @title BaseOwnable - Provides simple ownership access control.
/// @author Cobo Safe Dev Team https://www.cobo.com/
/// @dev Can be used in both proxy and non-proxy mode.
abstract contract BaseOwnable is BaseVersion {
address public owner;
address public pendingOwner;
bool private initialized = false;
event PendingOwnerSet(address indexed to);
event NewOwnerSet(address indexed owner);
modifier onlyOwner() {
require(owner == msg.sender, Errors.CALLER_IS_NOT_OWNER);
_;
}
/// @dev `owner` is set by argument, thus the owner can any address.
/// When used in non-proxy mode, `initialize` can not be called
/// after deployment.
constructor(address _owner) {
initialize(_owner);
}
/// @dev When used in proxy mode, `initialize` can be called by anyone
/// to claim the ownership.
/// This function can be called only once.
function initialize(address _owner) public {
require(!initialized, Errors.ALREADY_INITIALIZED);
_setOwner(_owner);
initialized = true;
}
/// @notice User should ensure the corrent owner address set, or the
/// ownership may be transferred to blackhole. It is recommended to
/// take a safer way with setPendingOwner() + acceptOwner().
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "New Owner is zero");
_setOwner(newOwner);
}
/// @notice The original owner calls `setPendingOwner(newOwner)` and the new
/// owner calls `acceptOwner()` to take the ownership.
function setPendingOwner(address to) external onlyOwner {
pendingOwner = to;
emit PendingOwnerSet(pendingOwner);
}
function acceptOwner() external {
require(msg.sender == pendingOwner);
_setOwner(pendingOwner);
}
/// @notice Make the contract immutable.
function renounceOwnership() external onlyOwner {
_setOwner(address(0));
}
// Internal functions
/// @dev Clear pendingOwner to prevent from reclaiming the ownership.
function _setOwner(address _owner) internal {
owner = _owner;
pendingOwner = address(0);
emit NewOwnerSet(owner);
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
/// @dev Common errors. This helps reducing the contract size.
library Errors {
// "E1";
// Call/Static-call failed.
string constant CALL_FAILED = "E2";
// Argument's type not supported in View Variant.
string constant INVALID_VIEW_ARG_SOL_TYPE = "E3";
// Invalid length for variant raw data.
string constant INVALID_VARIANT_RAW_DATA = "E4";
// "E5";
// Invalid variant type.
string constant INVALID_VAR_TYPE = "E6";
// Rule not exists
string constant RULE_NOT_EXISTS = "E7";
// Variant name not found.
string constant VAR_NAME_NOT_FOUND = "E8";
// Rule: v1/v2 solType mismatch
string constant SOL_TYPE_MISMATCH = "E9";
// "E10";
// Invalid rule OP.
string constant INVALID_RULE_OP = "E11";
// "E12";
// "E13";
// "E14";
// "E15";
// "E16";
// "E17";
// "E18";
// "E19";
// "E20";
// checkCmpOp: OP not support
string constant CMP_OP_NOT_SUPPORT = "E21";
// checkBySolType: Invalid op for bool
string constant INVALID_BOOL_OP = "E22";
// checkBySolType: Invalid op
string constant CHECK_INVALID_OP = "E23";
// Invalid solidity type.
string constant INVALID_SOL_TYPE = "E24";
// computeBySolType: invalid vm op
string constant INVALID_VM_BOOL_OP = "E25";
// computeBySolType: invalid vm arith op
string constant INVALID_VM_ARITH_OP = "E26";
// onlyCaller: Invalid caller
string constant INVALID_CALLER = "E27";
// "E28";
// Side-effect is not allowed here.
string constant SIDE_EFFECT_NOT_ALLOWED = "E29";
// Invalid variant count for the rule op.
string constant INVALID_VAR_COUNT = "E30";
// extractCallData: Invalid op.
string constant INVALID_EXTRACTOR_OP = "E31";
// extractCallData: Invalid array index.
string constant INVALID_ARRAY_INDEX = "E32";
// extractCallData: No extract op.
string constant NO_EXTRACT_OP = "E33";
// extractCallData: No extract path.
string constant NO_EXTRACT_PATH = "E34";
// BaseOwnable: caller is not owner
string constant CALLER_IS_NOT_OWNER = "E35";
// BaseOwnable: Already initialized
string constant ALREADY_INITIALIZED = "E36";
// "E37";
// "E38";
// BaseACL: ACL check method should not return anything.
string constant ACL_FUNC_RETURNS_NON_EMPTY = "E39";
// "E40";
// BaseAccount: Invalid delegate.
string constant INVALID_DELEGATE = "E41";
// RootAuthorizer: delegateCallAuthorizer not set
string constant DELEGATE_CALL_AUTH_NOT_SET = "E42";
// RootAuthorizer: callAuthorizer not set.
string constant CALL_AUTH_NOT_SET = "E43";
// BaseAccount: Authorizer not set.
string constant AUTHORIZER_NOT_SET = "E44";
// BaseAccount: Invalid authorizer flag.
string constant INVALID_AUTHORIZER_FLAG = "E45";
// BaseAuthorizer: Authorizer paused.
string constant AUTHORIZER_PAUSED = "E46";
// Authorizer set: Invalid hint.
string constant INVALID_HINT = "E47";
// Authorizer set: All auth deny.
string constant ALL_AUTH_FAILED = "E48";
// BaseACL: Method not allow.
string constant METHOD_NOT_ALLOW = "E49";
// AuthorizerUnionSet: Invalid hint collected.
string constant INVALID_HINT_COLLECTED = "E50";
// AuthorizerSet: Empty auth set
string constant EMPTY_AUTH_SET = "E51";
// AuthorizerSet: hint not implement.
string constant HINT_NOT_IMPLEMENT = "E52";
// RoleAuthorizer: Empty role set
string constant EMPTY_ROLE_SET = "E53";
// RoleAuthorizer: No auth for the role
string constant NO_AUTH_FOR_THE_ROLE = "E54";
// BaseACL: No in contract white list.
string constant NOT_IN_CONTRACT_LIST = "E55";
// BaseACL: Same process not allowed to install twice.
string constant SAME_PROCESS_TWICE = "E56";
// BaseAuthorizer: Account not set (then can not find roleManger)
string constant ACCOUNT_NOT_SET = "E57";
// BaseAuthorizer: roleManger not set
string constant ROLE_MANAGER_NOT_SET = "E58";
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "IVersion.sol";
/// @title BaseVersion - Provides version information
/// @author Cobo Safe Dev Team https://www.cobo.com/
/// @dev
/// Implement NAME() and VERSION() methods according to IVersion interface.
///
/// Or just:
/// bytes32 public constant NAME = "<Your contract name>";
/// uint256 public constant VERSION = <Your contract version>;
///
/// Change the NAME when writing new kind of contract.
/// Change the VERSION when upgrading existing contract.
abstract contract BaseVersion is IVersion {
/// @dev Convert to `string` which looks prettier on Etherscan viewer.
function _NAME() external view virtual returns (string memory) {
return string(abi.encodePacked(this.NAME()));
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
interface IVersion {
function NAME() external view returns (bytes32 name);
function VERSION() external view returns (uint256 version);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "Types.sol";
interface IAuthorizer {
function flag() external view returns (uint256 authFlags);
function setCaller(address _caller) external;
function preExecCheck(TransactionData calldata transaction) external returns (AuthorizerReturnData memory authData);
function postExecCheck(
TransactionData calldata transaction,
TransactionResult calldata callResult,
AuthorizerReturnData calldata preAuthData
) external returns (AuthorizerReturnData memory authData);
function preExecProcess(TransactionData calldata transaction) external;
function postExecProcess(TransactionData calldata transaction, TransactionResult calldata callResult) external;
}
interface IAuthorizerSupportingHint is IAuthorizer {
// When IAuthorizer(auth).flag().supportHint() == true;
function collectHint(
AuthorizerReturnData calldata preAuthData,
AuthorizerReturnData calldata postAuthData
) external view returns (bytes memory hint);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
enum AuthResult {
FAILED,
SUCCESS
}
struct CallData {
uint256 flag; // 0x1 delegate call, 0x0 call.
address to;
uint256 value;
bytes data; // calldata
bytes hint;
bytes extra; // for future support: signatures etc.
}
struct TransactionData {
address from; // Sender who performs the transaction a.k.a wallet address.
address delegate; // Delegate who calls executeTransactions().
// Same as CallData
uint256 flag; // 0x1 delegate call, 0x0 call.
address to;
uint256 value;
bytes data; // calldata
bytes hint;
bytes extra;
}
struct AuthorizerReturnData {
AuthResult result;
string message;
bytes data; // Authorizer return data. usually used for hint purpose.
}
struct TransactionResult {
bool success; // Call status.
bytes data; // Return/Revert data.
bytes hint;
}
library TxFlags {
uint256 internal constant DELEGATE_CALL_MASK = 0x1; // 1 for delegatecall, 0 for call
function isDelegateCall(uint256 flag) internal pure returns (bool) {
return flag & DELEGATE_CALL_MASK == DELEGATE_CALL_MASK;
}
}
library VarName {
bytes5 internal constant TEMP = "temp.";
function isTemp(bytes32 name) internal pure returns (bool) {
return bytes5(name) == TEMP;
}
}
library AuthType {
bytes32 internal constant FUNC = "FunctionType";
bytes32 internal constant TRANSFER = "TransferType";
bytes32 internal constant DEX = "DexType";
bytes32 internal constant LENDING = "LendingType";
bytes32 internal constant COMMON = "CommonType";
bytes32 internal constant SET = "SetType";
bytes32 internal constant VM = "VM";
}
library AuthFlags {
uint256 internal constant HAS_PRE_CHECK_MASK = 0x1;
uint256 internal constant HAS_POST_CHECK_MASK = 0x2;
uint256 internal constant HAS_PRE_PROC_MASK = 0x4;
uint256 internal constant HAS_POST_PROC_MASK = 0x8;
uint256 internal constant SUPPORT_HINT_MASK = 0x40;
uint256 internal constant FULL_MODE =
HAS_PRE_CHECK_MASK | HAS_POST_CHECK_MASK | HAS_PRE_PROC_MASK | HAS_POST_PROC_MASK;
function isValid(uint256 flag) internal pure returns (bool) {
// At least one check handler is activated.
return hasPreCheck(flag) || hasPostCheck(flag);
}
function hasPreCheck(uint256 flag) internal pure returns (bool) {
return flag & HAS_PRE_CHECK_MASK == HAS_PRE_CHECK_MASK;
}
function hasPostCheck(uint256 flag) internal pure returns (bool) {
return flag & HAS_POST_CHECK_MASK == HAS_POST_CHECK_MASK;
}
function hasPreProcess(uint256 flag) internal pure returns (bool) {
return flag & HAS_PRE_PROC_MASK == HAS_PRE_PROC_MASK;
}
function hasPostProcess(uint256 flag) internal pure returns (bool) {
return flag & HAS_POST_PROC_MASK == HAS_POST_PROC_MASK;
}
function supportHint(uint256 flag) internal pure returns (bool) {
return flag & SUPPORT_HINT_MASK == SUPPORT_HINT_MASK;
}
}
// For Rule VM.
// For each VariantType, an extractor should be implement.
enum VariantType {
INVALID, // Mark for delete.
EXTRACT_CALLDATA, // extract calldata by path bytes.
NAME, // name for user-defined variant.
RAW, // encoded solidity values.
VIEW, // staticcall view non-side-effect function and get return value.
CALL, // call state changing function and get returned value.
RULE, // rule expression.
ANY
}
// How the data should be decoded.
enum SolidityType {
_invalid, // Mark for delete.
_any,
_bytes,
_bool,
///// START 1
///// Generated by gen_rulelib.py (start)
_address,
_uint256,
_int256,
///// Generated by gen_rulelib.py (end)
///// END 1
_end
}
// A common operand in rule.
struct Variant {
VariantType varType;
SolidityType solType;
bytes data;
}
// OpCode for rule expression which returns v0.
enum OP {
INVALID,
// One opnd.
VAR, // v1
NOT, // !v1
// Two opnds.
// checkBySolType() which returns boolean.
EQ, // v1 == v2
NE, // v1 != v2
GT, // v1 > v2
GE, // v1 >= v2
LT, // v1 < v2
LE, // v1 <= v2
IN, // v1 in [...]
NOTIN, // v1 not in [...]
// computeBySolType() which returns bytes (with same solType)
AND, // v1 & v2
OR, // v1 | v2
ADD, // v1 + v2
SUB, // v1 - v2
MUL, // v1 * v2
DIV, // v1 / v2
MOD, // v1 % v2
// Three opnds.
IF, // v1? v2: v3
// Side-effect ones.
ASSIGN, // v1 := v2
VM, // rule list bytes.
NOP // as end.
}
struct Rule {
OP op;
Variant[] vars;
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "Types.sol";
interface IAccount {
/// @notice Call Gnosis Safe to execute a transaction
/// @dev Delegates can call this method to invoke gnosis safe to forward to
/// transaction to target contract
/// The function can only be called by delegates.
/// @param callData The callData to be called by Gnosis Safe
function execTransaction(CallData calldata callData) external returns (TransactionResult memory result);
function execTransactions(
CallData[] calldata callDataList
) external returns (TransactionResult[] memory resultList);
function setAuthorizer(address _authorizer) external;
function setRoleManager(address _roleManager) external;
function addDelegate(address _delegate) external;
function addDelegates(address[] calldata _delegates) external;
/// @dev Sub instance should override this to set `from` for transaction
/// @return account The address for the contract wallet, also the
/// `msg.sender` address which send the transaction.
function getAccountAddress() external view returns (address account);
function roleManager() external view returns (address _roleManager);
function authorizer() external view returns (address _authorizer);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
import "Types.sol";
interface IRoleManager {
function getRoles(address delegate) external view returns (bytes32[] memory);
function hasRole(address delegate, bytes32 role) external view returns (bool);
}
interface IFlatRoleManager is IRoleManager {
function addRoles(bytes32[] calldata roles) external;
function grantRoles(bytes32[] calldata roles, address[] calldata delegates) external;
function revokeRoles(bytes32[] calldata roles, address[] calldata delegates) external;
function getDelegates() external view returns (address[] memory);
function getAllRoles() external view returns (bytes32[] memory);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.19;
address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address constant ZERO_ADDRESS = address(0);
function getWrappedTokenAddress() view returns (address tokenAddress) {
uint256 chainId = block.chainid;
// ETH: WETH
if (chainId == 1) return 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
// Optimism: WETH
if (chainId == 10) return 0x4200000000000000000000000000000000000006;
// BSC: WBNB
if (chainId == 56) return 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
// Polygon: WMATIC
if (chainId == 137) return 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270;
// Arbitrum: WETH
if (chainId == 42161) return 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
// Avalanche: WAVAX
if (chainId == 43114) return 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7;
revert("Unsupport chain");
}{
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 200
},
"libraries": {
"OneinchV5Authorizer.sol": {}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_caller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AccountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"CallerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"NewOwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"status","type":"bool"}],"name":"PausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PendingOwnerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"SwapInTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"SwapInTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"SwapOutTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"SwapOutTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"tag","type":"bytes32"}],"name":"TagSet","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"account","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"addSwapInTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"addSwapOutTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"caller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"clipperExchange","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"goodUntil","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"}],"name":"clipperSwap","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contracts","outputs":[{"internalType":"address[]","name":"_contracts","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"uint256","name":"offsets","type":"uint256"},{"internalType":"bytes","name":"interactions","type":"bytes"}],"internalType":"struct OneinchV5Authorizer.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"interaction","type":"bytes"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"},{"internalType":"uint256","name":"skipPermitAndThresholdAmount","type":"uint256"}],"name":"fillOrder","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"info","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"internalType":"struct OneinchV5Authorizer.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"}],"name":"fillOrderRFQ","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"info","type":"uint256"},{"internalType":"address","name":"makerAsset","type":"address"},{"internalType":"address","name":"takerAsset","type":"address"},{"internalType":"address","name":"maker","type":"address"},{"internalType":"address","name":"allowedSender","type":"address"},{"internalType":"uint256","name":"makingAmount","type":"uint256"},{"internalType":"uint256","name":"takingAmount","type":"uint256"}],"internalType":"struct OneinchV5Authorizer.OrderRFQ","name":"order","type":"tuple"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"vs","type":"bytes32"},{"internalType":"uint256","name":"flagsAndAmount","type":"uint256"}],"name":"fillOrderRFQCompact","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flag","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapInTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapOutTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"hasSwapInToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"hasSwapOutToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_caller","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_caller","type":"address"},{"internalType":"address","name":"_account","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"flag","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"},{"internalType":"bytes","name":"extra","type":"bytes"}],"internalType":"struct TransactionData","name":"transaction","type":"tuple"},{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"}],"internalType":"struct TransactionResult","name":"callResult","type":"tuple"},{"components":[{"internalType":"enum AuthResult","name":"result","type":"uint8"},{"internalType":"string","name":"message","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct AuthorizerReturnData","name":"preData","type":"tuple"}],"name":"postExecCheck","outputs":[{"components":[{"internalType":"enum AuthResult","name":"result","type":"uint8"},{"internalType":"string","name":"message","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct AuthorizerReturnData","name":"authData","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"flag","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"},{"internalType":"bytes","name":"extra","type":"bytes"}],"internalType":"struct TransactionData","name":"transaction","type":"tuple"},{"components":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"}],"internalType":"struct TransactionResult","name":"callResult","type":"tuple"}],"name":"postExecProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"flag","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"},{"internalType":"bytes","name":"extra","type":"bytes"}],"internalType":"struct TransactionData","name":"transaction","type":"tuple"}],"name":"preExecCheck","outputs":[{"components":[{"internalType":"enum AuthResult","name":"result","type":"uint8"},{"internalType":"string","name":"message","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct AuthorizerReturnData","name":"authData","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"flag","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"hint","type":"bytes"},{"internalType":"bytes","name":"extra","type":"bytes"}],"internalType":"struct TransactionData","name":"transaction","type":"tuple"}],"name":"preExecProcess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"removeSwapInTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"removeSwapOutTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"setAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"}],"name":"setCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_tag","type":"bytes32"}],"name":"setTag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"address","name":"srcReceiver","type":"address"},{"internalType":"address","name":"dstReceiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturnAmount","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"internalType":"struct OneinchV5Authorizer.SwapDescription","name":"_desc","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tag","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"pools","type":"uint256[]"}],"name":"uniswapV3Swap","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_srcToken","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"pools","type":"uint256[]"}],"name":"unoswap","outputs":[],"stateMutability":"view","type":"function"}]Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.