Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19340815 | 316 days ago | 1.3 ETH | ||||
19340483 | 316 days ago | 0.02 ETH | ||||
19340420 | 316 days ago | 0.02 ETH | ||||
19338598 | 316 days ago | 0.02 ETH | ||||
19338469 | 316 days ago | 0.02 ETH | ||||
19338432 | 316 days ago | 0.02 ETH | ||||
19338415 | 316 days ago | 0.02 ETH | ||||
19336481 | 317 days ago | 0.02 ETH | ||||
19336144 | 317 days ago | 0.04 ETH | ||||
19334965 | 317 days ago | 0.02 ETH | ||||
19334444 | 317 days ago | 0.04 ETH | ||||
19328536 | 318 days ago | 0.04 ETH | ||||
19323663 | 319 days ago | 0.02 ETH | ||||
19320533 | 319 days ago | 0.1 ETH | ||||
19320234 | 319 days ago | 0.06 ETH | ||||
19320186 | 319 days ago | 0.04 ETH | ||||
19320174 | 319 days ago | 0.06 ETH | ||||
19320174 | 319 days ago | 0.2 ETH | ||||
19320172 | 319 days ago | 0.1 ETH | ||||
19320163 | 319 days ago | 0.2 ETH | ||||
19320157 | 319 days ago | 0.2 ETH | ||||
19315597 | 320 days ago | 0.4 ETH | ||||
19314518 | 320 days ago | 0.04 ETH | ||||
19300407 | 322 days ago | 0.04 ETH | ||||
19300253 | 322 days ago | 0.02 ETH |
Loading...
Loading
Minimal Proxy Contract for 0x7fcdd45101e35fd626a539ba565d26a72d95fda7
Contract Name:
SwapperImpl
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC20} from "solmate/tokens/ERC20.sol"; import {IOracle} from "splits-oracle/interfaces/IOracle.sol"; import {PausableImpl} from "splits-utils/PausableImpl.sol"; import {QuotePair, QuoteParams, SortedQuotePair} from "splits-utils/LibQuotes.sol"; import {SafeCastLib} from "solady/utils/SafeCastLib.sol"; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; import {TokenUtils} from "splits-utils/TokenUtils.sol"; import {WalletImpl} from "splits-utils/WalletImpl.sol"; import {ISwapperFlashCallback} from "./interfaces/ISwapperFlashCallback.sol"; import {PairScaledOfferFactors} from "./libraries/PairScaledOfferFactors.sol"; /// @title Swapper Implementation /// @author 0xSplits /// @notice A contract to trustlessly & automatically convert multi-token /// onchain revenue into a particular output token. /// Please be aware, owner has _FULL CONTROL_ of the deployment. /// @dev This contract uses a modular oracle. Be very careful to use a secure /// oracle with sensible settings for the desired behavior. Insecure oracles /// will result in catastrophic loss of funds. /// This contract uses token = address(0) to refer to ETH. contract SwapperImpl is WalletImpl, PausableImpl { /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- using SafeTransferLib for address; using SafeCastLib for uint256; using TokenUtils for address; using PairScaledOfferFactors for mapping(address => mapping(address => uint32)); /// ----------------------------------------------------------------------- /// errors /// ----------------------------------------------------------------------- error Invalid_AmountsToBeneficiary(); error Invalid_QuoteToken(); error InsufficientFunds_InContract(); error InsufficientFunds_FromTrader(); /// ----------------------------------------------------------------------- /// structs /// ----------------------------------------------------------------------- struct InitParams { address owner; bool paused; address beneficiary; address tokenToBeneficiary; IOracle oracle; uint32 defaultScaledOfferFactor; SetPairScaledOfferFactorParams[] pairScaledOfferFactors; } struct SetPairScaledOfferFactorParams { QuotePair quotePair; uint32 scaledOfferFactor; } /// ----------------------------------------------------------------------- /// events /// ----------------------------------------------------------------------- event SetBeneficiary(address beneficiary); event SetTokenToBeneficiary(address tokenToBeneficiary); event SetOracle(IOracle oracle); event SetDefaultScaledOfferFactor(uint32 defaultScaledOfferFactor); event SetPairScaledOfferFactors(SetPairScaledOfferFactorParams[] params); event ReceiveETH(uint256 amount); event Payback(address indexed payer, uint256 amount); event Flash( address indexed beneficiary, address indexed trader, QuoteParams[] quoteParams, address tokenToBeneficiary, uint256[] amountsToBeneficiary, uint256 excessToBeneficiary ); /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// storage - constants & immutables /// ----------------------------------------------------------------------- address public immutable swapperFactory; /// @dev percentages measured in hundredths of basis points uint32 internal constant PERCENTAGE_SCALE = 100_00_00; // = 100% /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 11 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes /// PausableImpl storage /// bool internal $paused; /// 1 byte /// slot 1 - 0 bytes free /// address to receive post-swap tokens address internal $beneficiary; /// 20 bytes /// used to track ETH payback in flash uint96 internal $_payback; /// 12 bytes /// slot 2 - 8 bytes free /// token type to send beneficiary /// @dev 0x0 used for ETH address internal $tokenToBeneficiary; /// 20 bytes /// default oracle price scaling factor /// @dev PERCENTAGE_SCALE = 1e6 = 100_00_00 = 100% = no discount or premium /// 99_00_00 = 99% = 1% discount to oracle; 101_00_00 = 101% = 1% premium to oracle /// 4 bytes uint32 internal $defaultScaledOfferFactor; /// slot 3 - 12 bytes free /// price oracle for `#flash` IOracle internal $oracle; /// 20 bytes /// slot 4 - 0 bytes free /// scaledOfferFactors for specific quote pairs /// 32 bytes mapping(address => mapping(address => uint32)) internal $_pairScaledOfferFactors; /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() { swapperFactory = msg.sender; } function initializer(InitParams calldata params_) external { // only swapperFactory may call `initializer` if (msg.sender != swapperFactory) revert Unauthorized(); // don't need to init wallet separately __initPausable({owner_: params_.owner, paused_: params_.paused}); $beneficiary = params_.beneficiary; $tokenToBeneficiary = params_.tokenToBeneficiary; $oracle = params_.oracle; $defaultScaledOfferFactor = params_.defaultScaledOfferFactor; $_pairScaledOfferFactors._set(params_.pairScaledOfferFactors); } /// ----------------------------------------------------------------------- /// functions /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- /// set beneficiary function setBeneficiary(address beneficiary_) external onlyOwner { $beneficiary = beneficiary_; emit SetBeneficiary(beneficiary_); } /// set tokenToBeneficiary function setTokenToBeneficiary(address tokenToBeneficiary_) external onlyOwner { $tokenToBeneficiary = tokenToBeneficiary_; emit SetTokenToBeneficiary(tokenToBeneficiary_); } /// set oracle function setOracle(IOracle oracle_) external onlyOwner { $oracle = oracle_; emit SetOracle(oracle_); } /// set defaultScaledOfferFactor function setDefaultScaledOfferFactor(uint32 defaultScaledOfferFactor_) external onlyOwner { $defaultScaledOfferFactor = defaultScaledOfferFactor_; emit SetDefaultScaledOfferFactor(defaultScaledOfferFactor_); } /// set pair scaled offer factors function setPairScaledOfferFactors(SetPairScaledOfferFactorParams[] calldata params_) external onlyOwner { $_pairScaledOfferFactors._set(params_); emit SetPairScaledOfferFactors(params_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function beneficiary() external view returns (address) { return $beneficiary; } function tokenToBeneficiary() external view returns (address) { return $tokenToBeneficiary; } function oracle() external view returns (IOracle) { return $oracle; } function defaultScaledOfferFactor() external view returns (uint32) { return $defaultScaledOfferFactor; } /// get pair scaled offer factors for an array of quote pairs function getPairScaledOfferFactors(QuotePair[] calldata quotePairs_) external view returns (uint32[] memory pairScaledOfferFactors) { uint256 length = quotePairs_.length; pairScaledOfferFactors = new uint32[](length); for (uint256 i; i < length;) { pairScaledOfferFactors[i] = $_pairScaledOfferFactors._get(quotePairs_[i]); unchecked { ++i; } } } /// ----------------------------------------------------------------------- /// functions - public & external - permissionless /// ----------------------------------------------------------------------- /// emit event when receiving ETH /// @dev implemented w/i clone bytecode /* receive() external payable { */ /* emit ReceiveETH(msg.value); */ /* } */ /// allows `#flash` to track ETH payback to `beneficiary` /// @dev if used outside `#swapperFlashCallback`, msg.sender may lose funds. /// Accumulates until next flash call function payback() external payable { $_payback += msg.value.toUint96(); emit Payback(msg.sender, msg.value); } /// allow third parties to withdraw tokens in return for sending `tokenToBeneficiary` to `beneficiary` function flash(QuoteParams[] calldata quoteParams_, bytes calldata callbackData_) external pausable returns (uint256) { address _tokenToBeneficiary = $tokenToBeneficiary; (uint256 amountToBeneficiary, uint256[] memory amountsToBeneficiary) = _transferToTrader(_tokenToBeneficiary, quoteParams_); ISwapperFlashCallback(msg.sender).swapperFlashCallback({ tokenToBeneficiary: _tokenToBeneficiary, amountToBeneficiary: amountToBeneficiary, data: callbackData_ }); address _beneficiary = $beneficiary; uint256 excessToBeneficiary = _transferToBeneficiary(_beneficiary, _tokenToBeneficiary, amountToBeneficiary); emit Flash( _beneficiary, msg.sender, quoteParams_, _tokenToBeneficiary, amountsToBeneficiary, excessToBeneficiary ); return amountToBeneficiary + excessToBeneficiary; } /// ----------------------------------------------------------------------- /// functions - private & internal /// ----------------------------------------------------------------------- function _transferToTrader(address tokenToBeneficiary_, QuoteParams[] calldata quoteParams_) internal returns (uint256 amountToBeneficiary, uint256[] memory amountsToBeneficiary) { uint256[] memory unscaledAmountsToBeneficiary = $oracle.getQuoteAmounts(quoteParams_); uint256 length = quoteParams_.length; if (unscaledAmountsToBeneficiary.length != length) revert Invalid_AmountsToBeneficiary(); amountsToBeneficiary = new uint256[](length); uint256 scaledAmountToBeneficiary; uint128 amountToTrader; address tokenToTrader; for (uint256 i; i < length;) { QuoteParams calldata qp = quoteParams_[i]; if (tokenToBeneficiary_ != qp.quotePair.quote) revert Invalid_QuoteToken(); tokenToTrader = qp.quotePair.base; amountToTrader = qp.baseAmount; if (amountToTrader > tokenToTrader._balanceOf(address(this))) { revert InsufficientFunds_InContract(); } uint32 scaledOfferFactor = $_pairScaledOfferFactors._get(qp.quotePair._sort()); if (scaledOfferFactor == 0) { scaledOfferFactor = $defaultScaledOfferFactor; } scaledAmountToBeneficiary = unscaledAmountsToBeneficiary[i] * scaledOfferFactor / PERCENTAGE_SCALE; amountsToBeneficiary[i] = scaledAmountToBeneficiary; amountToBeneficiary += scaledAmountToBeneficiary; tokenToTrader._safeTransfer(msg.sender, amountToTrader); unchecked { ++i; } } } function _transferToBeneficiary(address beneficiary_, address tokenToBeneficiary_, uint256 amountToBeneficiary_) internal returns (uint256 excessToBeneficiary) { if (tokenToBeneficiary_._isETH()) { if ($_payback < amountToBeneficiary_) { revert InsufficientFunds_FromTrader(); } $_payback = 0; // send ETH to `beneficiary` uint256 ethBalance = address(this).balance; excessToBeneficiary = ethBalance - amountToBeneficiary_; beneficiary_.safeTransferETH(ethBalance); } else { tokenToBeneficiary_.safeTransferFrom(msg.sender, beneficiary_, amountToBeneficiary_); // flush excess `tokenToBeneficiary` to `beneficiary` excessToBeneficiary = ERC20(tokenToBeneficiary_).balanceOf(address(this)); if (excessToBeneficiary > 0) { tokenToBeneficiary_.safeTransfer(beneficiary_, excessToBeneficiary); } } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {QuoteParams} from "splits-utils/LibQuotes.sol"; /// @title Oracle Interface /// @author 0xSplits interface IOracle { function getQuoteAmounts(QuoteParams[] calldata quoteParams_) external view returns (uint256[] memory); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {OwnableImpl} from "./OwnableImpl.sol"; /// @title Pausable Implementation /// @author 0xSplits /// @notice Pausable clone-implementation abstract contract PausableImpl is OwnableImpl { error Paused(); event SetPaused(bool paused); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 11 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes bool internal $paused; /// 1 byte /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initPausable(address owner_, bool paused_) internal virtual { OwnableImpl.__initOwnable(owner_); $paused = paused_; } /// ----------------------------------------------------------------------- /// modifiers /// ----------------------------------------------------------------------- modifier pausable() virtual { if (paused()) revert Paused(); _; } /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- function setPaused(bool paused_) public virtual onlyOwner { $paused = paused_; emit SetPaused(paused_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function paused() public view virtual returns (bool) { return $paused; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ConvertedQuotePair, SortedConvertedQuotePair} from "./ConvertedQuotePair.sol"; using {_sort, _convert, _convertAndSort} for QuotePair global; struct QuoteParams { QuotePair quotePair; uint128 baseAmount; bytes data; } struct QuotePair { address base; address quote; } struct SortedQuotePair { address token0; address token1; } function _sort(QuotePair memory qp) pure returns (SortedQuotePair memory) { return (qp.base > qp.quote) ? SortedQuotePair({token0: qp.quote, token1: qp.base}) : SortedQuotePair({token0: qp.base, token1: qp.quote}); } function _convert(QuotePair calldata qp, function (address) internal view returns (address) convert) view returns (ConvertedQuotePair memory) { return ConvertedQuotePair({cBase: convert(qp.base), cQuote: convert(qp.quote)}); } function _convertAndSort(QuotePair calldata qp, function (address) internal view returns (address) convert) view returns (SortedConvertedQuotePair memory) { return _convert(qp, convert)._sort(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe integer casting library that reverts on overflow. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error Overflow(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* UNSIGNED INTEGER SAFE CASTING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toUint8(uint256 x) internal pure returns (uint8) { if (x >= 1 << 8) _revertOverflow(); return uint8(x); } function toUint16(uint256 x) internal pure returns (uint16) { if (x >= 1 << 16) _revertOverflow(); return uint16(x); } function toUint24(uint256 x) internal pure returns (uint24) { if (x >= 1 << 24) _revertOverflow(); return uint24(x); } function toUint32(uint256 x) internal pure returns (uint32) { if (x >= 1 << 32) _revertOverflow(); return uint32(x); } function toUint40(uint256 x) internal pure returns (uint40) { if (x >= 1 << 40) _revertOverflow(); return uint40(x); } function toUint48(uint256 x) internal pure returns (uint48) { if (x >= 1 << 48) _revertOverflow(); return uint48(x); } function toUint56(uint256 x) internal pure returns (uint56) { if (x >= 1 << 56) _revertOverflow(); return uint56(x); } function toUint64(uint256 x) internal pure returns (uint64) { if (x >= 1 << 64) _revertOverflow(); return uint64(x); } function toUint72(uint256 x) internal pure returns (uint72) { if (x >= 1 << 72) _revertOverflow(); return uint72(x); } function toUint80(uint256 x) internal pure returns (uint80) { if (x >= 1 << 80) _revertOverflow(); return uint80(x); } function toUint88(uint256 x) internal pure returns (uint88) { if (x >= 1 << 88) _revertOverflow(); return uint88(x); } function toUint96(uint256 x) internal pure returns (uint96) { if (x >= 1 << 96) _revertOverflow(); return uint96(x); } function toUint104(uint256 x) internal pure returns (uint104) { if (x >= 1 << 104) _revertOverflow(); return uint104(x); } function toUint112(uint256 x) internal pure returns (uint112) { if (x >= 1 << 112) _revertOverflow(); return uint112(x); } function toUint120(uint256 x) internal pure returns (uint120) { if (x >= 1 << 120) _revertOverflow(); return uint120(x); } function toUint128(uint256 x) internal pure returns (uint128) { if (x >= 1 << 128) _revertOverflow(); return uint128(x); } function toUint136(uint256 x) internal pure returns (uint136) { if (x >= 1 << 136) _revertOverflow(); return uint136(x); } function toUint144(uint256 x) internal pure returns (uint144) { if (x >= 1 << 144) _revertOverflow(); return uint144(x); } function toUint152(uint256 x) internal pure returns (uint152) { if (x >= 1 << 152) _revertOverflow(); return uint152(x); } function toUint160(uint256 x) internal pure returns (uint160) { if (x >= 1 << 160) _revertOverflow(); return uint160(x); } function toUint168(uint256 x) internal pure returns (uint168) { if (x >= 1 << 168) _revertOverflow(); return uint168(x); } function toUint176(uint256 x) internal pure returns (uint176) { if (x >= 1 << 176) _revertOverflow(); return uint176(x); } function toUint184(uint256 x) internal pure returns (uint184) { if (x >= 1 << 184) _revertOverflow(); return uint184(x); } function toUint192(uint256 x) internal pure returns (uint192) { if (x >= 1 << 192) _revertOverflow(); return uint192(x); } function toUint200(uint256 x) internal pure returns (uint200) { if (x >= 1 << 200) _revertOverflow(); return uint200(x); } function toUint208(uint256 x) internal pure returns (uint208) { if (x >= 1 << 208) _revertOverflow(); return uint208(x); } function toUint216(uint256 x) internal pure returns (uint216) { if (x >= 1 << 216) _revertOverflow(); return uint216(x); } function toUint224(uint256 x) internal pure returns (uint224) { if (x >= 1 << 224) _revertOverflow(); return uint224(x); } function toUint232(uint256 x) internal pure returns (uint232) { if (x >= 1 << 232) _revertOverflow(); return uint232(x); } function toUint240(uint256 x) internal pure returns (uint240) { if (x >= 1 << 240) _revertOverflow(); return uint240(x); } function toUint248(uint256 x) internal pure returns (uint248) { if (x >= 1 << 248) _revertOverflow(); return uint248(x); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNED INTEGER SAFE CASTING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toInt8(int256 x) internal pure returns (int8) { int8 y = int8(x); if (x != y) _revertOverflow(); return y; } function toInt16(int256 x) internal pure returns (int16) { int16 y = int16(x); if (x != y) _revertOverflow(); return y; } function toInt24(int256 x) internal pure returns (int24) { int24 y = int24(x); if (x != y) _revertOverflow(); return y; } function toInt32(int256 x) internal pure returns (int32) { int32 y = int32(x); if (x != y) _revertOverflow(); return y; } function toInt40(int256 x) internal pure returns (int40) { int40 y = int40(x); if (x != y) _revertOverflow(); return y; } function toInt48(int256 x) internal pure returns (int48) { int48 y = int48(x); if (x != y) _revertOverflow(); return y; } function toInt56(int256 x) internal pure returns (int56) { int56 y = int56(x); if (x != y) _revertOverflow(); return y; } function toInt64(int256 x) internal pure returns (int64) { int64 y = int64(x); if (x != y) _revertOverflow(); return y; } function toInt72(int256 x) internal pure returns (int72) { int72 y = int72(x); if (x != y) _revertOverflow(); return y; } function toInt80(int256 x) internal pure returns (int80) { int80 y = int80(x); if (x != y) _revertOverflow(); return y; } function toInt88(int256 x) internal pure returns (int88) { int88 y = int88(x); if (x != y) _revertOverflow(); return y; } function toInt96(int256 x) internal pure returns (int96) { int96 y = int96(x); if (x != y) _revertOverflow(); return y; } function toInt104(int256 x) internal pure returns (int104) { int104 y = int104(x); if (x != y) _revertOverflow(); return y; } function toInt112(int256 x) internal pure returns (int112) { int112 y = int112(x); if (x != y) _revertOverflow(); return y; } function toInt120(int256 x) internal pure returns (int120) { int120 y = int120(x); if (x != y) _revertOverflow(); return y; } function toInt128(int256 x) internal pure returns (int128) { int128 y = int128(x); if (x != y) _revertOverflow(); return y; } function toInt136(int256 x) internal pure returns (int136) { int136 y = int136(x); if (x != y) _revertOverflow(); return y; } function toInt144(int256 x) internal pure returns (int144) { int144 y = int144(x); if (x != y) _revertOverflow(); return y; } function toInt152(int256 x) internal pure returns (int152) { int152 y = int152(x); if (x != y) _revertOverflow(); return y; } function toInt160(int256 x) internal pure returns (int160) { int160 y = int160(x); if (x != y) _revertOverflow(); return y; } function toInt168(int256 x) internal pure returns (int168) { int168 y = int168(x); if (x != y) _revertOverflow(); return y; } function toInt176(int256 x) internal pure returns (int176) { int176 y = int176(x); if (x != y) _revertOverflow(); return y; } function toInt184(int256 x) internal pure returns (int184) { int184 y = int184(x); if (x != y) _revertOverflow(); return y; } function toInt192(int256 x) internal pure returns (int192) { int192 y = int192(x); if (x != y) _revertOverflow(); return y; } function toInt200(int256 x) internal pure returns (int200) { int200 y = int200(x); if (x != y) _revertOverflow(); return y; } function toInt208(int256 x) internal pure returns (int208) { int208 y = int208(x); if (x != y) _revertOverflow(); return y; } function toInt216(int256 x) internal pure returns (int216) { int216 y = int216(x); if (x != y) _revertOverflow(); return y; } function toInt224(int256 x) internal pure returns (int224) { int224 y = int224(x); if (x != y) _revertOverflow(); return y; } function toInt232(int256 x) internal pure returns (int232) { int232 y = int232(x); if (x != y) _revertOverflow(); return y; } function toInt240(int256 x) internal pure returns (int240) { int240 y = int240(x); if (x != y) _revertOverflow(); return y; } function toInt248(int256 x) internal pure returns (int248) { int248 y = int248(x); if (x != y) _revertOverflow(); return y; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* UNSIGNED TO SIGNED SAFE CASTING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toInt256(uint256 x) internal pure returns (int256) { if (x >= 1 << 255) _revertOverflow(); return int256(x); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function _revertOverflow() private pure { /// @solidity memory-safe-assembly assembly { // Store the function selector of `Overflow()`. mstore(0x00, 0x35278d12) // Revert with (offset, size). revert(0x1c, 0x04) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH /// that disallows any storage writes. uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. /// Multiply by a small constant (e.g. 2), if needed. uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` (in wei) ETH to `to`. /// Reverts upon failure. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. if iszero(call(gas(), to, amount, 0, 0, 0, 0)) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { // For better gas estimation. if iszero(gt(gas(), 1000000)) { revert(0, 0) } } } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default /// for 99% of cases and can be overriden with the three-argument version of this /// function if necessary. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount) internal { // Manually inlined because the compiler doesn't inline functions with branches. /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { // For better gas estimation. if iszero(gt(gas(), 1000000)) { revert(0, 0) } } } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend. /// /// Note: Does NOT revert upon failure. /// Returns whether the transfer of ETH is successful instead. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. success := call(gasStipend, to, amount, 0, 0, 0, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x0c, 0x23b872dd000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. // Store the function selector of `balanceOf(address)`. mstore(0x0c, 0x70a08231000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) // The `amount` argument is already written to the memory word at 0x6c. amount := mload(0x60) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. // Store the function selector of `transfer(address,uint256)`. mstore(0x00, 0xa9059cbb000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. // The `amount` argument is already written to the memory word at 0x34. amount := mload(0x34) // Store the function selector of `transfer(address,uint256)`. mstore(0x00, 0xa9059cbb000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. // Store the function selector of `approve(address,uint256)`. mstore(0x00, 0x095ea7b3000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. // Store the function selector of `balanceOf(address)`. mstore(0x00, 0x70a08231000000000000000000000000) amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol"; /// Library to handle basic token functions for ERC20s & ETH (represented by 0x0) library TokenUtils { using SafeTransferLib for address; address internal constant ETH_ADDRESS = address(0); function _isETH(address token) internal pure returns (bool) { return (token == ETH_ADDRESS); } function _decimals(address token) internal view returns (uint8) { return _isETH(token) ? 18 : ERC20(token).decimals(); } function _balanceOf(address token, address addr) internal view returns (uint256) { return _isETH(token) ? addr.balance : ERC20(token).balanceOf(addr); } function _safeTransfer(address token, address addr, uint256 amount) internal { if (_isETH(token)) addr.safeTransferETH(amount); else token.safeTransfer(addr, amount); } } interface ERC20 { function decimals() external view returns (uint8); function balanceOf(address addr) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol"; import {ERC721TokenReceiver} from "solmate/tokens/ERC721.sol"; import {OwnableImpl} from "./OwnableImpl.sol"; /// @title Wallet Implementation /// @author 0xSplits /// @notice Minimal smart wallet clone-implementation abstract contract WalletImpl is OwnableImpl, ERC721TokenReceiver, ERC1155TokenReceiver { struct Call { address to; uint256 value; bytes data; } event ExecCalls(Call[] calls); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 12 bytes free /// OwnableImpl storage /// address internal $owner; /// 20 bytes /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initWallet(address owner_) internal { OwnableImpl.__initOwnable(owner_); } /// ----------------------------------------------------------------------- /// functions - external & public - onlyOwner /// ----------------------------------------------------------------------- /// allow owner to execute arbitrary calls function execCalls(Call[] calldata calls_) external payable onlyOwner returns (uint256 blockNumber, bytes[] memory returnData) { blockNumber = block.number; uint256 length = calls_.length; returnData = new bytes[](length); bool success; for (uint256 i; i < length;) { Call calldata calli = calls_[i]; (success, returnData[i]) = calli.to.call{value: calli.value}(calli.data); require(success, string(returnData[i])); unchecked { ++i; } } emit ExecCalls(calls_); } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; /// @title Swapper Flash Callback /// @author 0xSplits /// @notice Callback for `Swapper#flash` /// @dev any contract that calls `Swapper#flash` must implement this interface. /// Inspired by IUniswapV3FlashCallback interface ISwapperFlashCallback { /// Called to `msg.sender` in `Swapper#flash` after transferring `quoteParams`. /// @dev In the implementation you must complete the flash swap. /// If `tokenToBeneficiary` is ETH, you must deposit `amountToBeneficiary` via `Swapper#payback`. /// If `tokenToBeneficiary` is an ERC20, you must use approve Swapper to transfer `amountToBeneficiary`. /// The caller of this method will use token = address(0) to refer to ETH. /// @param tokenToBeneficiary The token due to the `beneficiary` by the end of `#flash` /// @param amountToBeneficiary The amount of `tokenToBeneficiary` due to the `beneficiary` by the end of `#flash` /// @param data Any `data` passed through by `msg.sender` of `Swapper#flash` function swapperFlashCallback(address tokenToBeneficiary, uint256 amountToBeneficiary, bytes calldata data) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {QuotePair, SortedQuotePair} from "splits-utils/LibQuotes.sol"; import {SwapperImpl} from "../SwapperImpl.sol"; /// @title PairScaledOfferFactors Library /// @author 0xSplits /// @notice Setters & getters for quote pairs' scaledOfferFactors library PairScaledOfferFactors { /// set pairs' scaled offer factors function _set( mapping(address => mapping(address => uint32)) storage self, SwapperImpl.SetPairScaledOfferFactorParams[] calldata params_ ) internal { uint256 length = params_.length; for (uint256 i; i < length;) { _set(self, params_[i]); unchecked { ++i; } } } /// set pair's scaled offer factor function _set( mapping(address => mapping(address => uint32)) storage self, SwapperImpl.SetPairScaledOfferFactorParams calldata params_ ) internal { SortedQuotePair memory sqp = params_.quotePair._sort(); self[sqp.token0][sqp.token1] = params_.scaledOfferFactor; } /// get pair's scaled offer factor function _get(mapping(address => mapping(address => uint32)) storage self, QuotePair calldata quotePair_) internal view returns (uint32) { return _get(self, quotePair_._sort()); } /// get pair's scaled offer factor function _get(mapping(address => mapping(address => uint32)) storage self, SortedQuotePair memory sqp_) internal view returns (uint32) { return self[sqp_.token0][sqp_.token1]; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; /// @title Ownable Implementation /// @author 0xSplits /// @notice Ownable clone-implementation abstract contract OwnableImpl { error Unauthorized(); event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// ----------------------------------------------------------------------- /// storage - mutables /// ----------------------------------------------------------------------- /// slot 0 - 12 bytes free address internal $owner; /// 20 bytes /// ----------------------------------------------------------------------- /// constructor & initializer /// ----------------------------------------------------------------------- constructor() {} function __initOwnable(address owner_) internal virtual { emit OwnershipTransferred(address(0), owner_); $owner = owner_; } /// ----------------------------------------------------------------------- /// modifiers /// ----------------------------------------------------------------------- modifier onlyOwner() virtual { if (msg.sender != owner()) revert Unauthorized(); _; } /// ----------------------------------------------------------------------- /// functions - public & external - onlyOwner /// ----------------------------------------------------------------------- function transferOwnership(address owner_) public virtual onlyOwner { $owner = owner_; emit OwnershipTransferred(msg.sender, owner_); } /// ----------------------------------------------------------------------- /// functions - public & external - view /// ----------------------------------------------------------------------- function owner() public view virtual returns (address) { return $owner; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; using {_sort} for ConvertedQuotePair global; struct ConvertedQuotePair { address cBase; address cQuote; } struct SortedConvertedQuotePair { address cToken0; address cToken1; } function _sort(ConvertedQuotePair memory cqp) pure returns (SortedConvertedQuotePair memory) { return (cqp.cBase > cqp.cQuote) ? SortedConvertedQuotePair({cToken0: cqp.cQuote, cToken1: cqp.cBase}) : SortedConvertedQuotePair({cToken0: cqp.cBase, cToken1: cqp.cQuote}); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
{ "remappings": [ "@uniswap/v3-core/=lib/splits-oracle/lib/v3-core/", "@uniswap/v3-periphery/=lib/v3-periphery/", "chainlink/=lib/splits-oracle/lib/chainlink/contracts/src/v0.8/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solady/=lib/solady/src/", "solmate/=lib/solmate/src/", "splits-oracle/=lib/splits-oracle/src/", "splits-tests/=lib/splits-utils/test/", "splits-utils/=lib/splits-utils/src/", "v3-core/=lib/splits-oracle/lib/v3-core/contracts/", "v3-periphery/=lib/v3-periphery/contracts/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientFunds_FromTrader","type":"error"},{"inputs":[],"name":"InsufficientFunds_InContract","type":"error"},{"inputs":[],"name":"Invalid_AmountsToBeneficiary","type":"error"},{"inputs":[],"name":"Invalid_QuoteToken","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct WalletImpl.Call[]","name":"calls","type":"tuple[]"}],"name":"ExecCalls","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"components":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair","name":"quotePair","type":"tuple"},{"internalType":"uint128","name":"baseAmount","type":"uint128"},{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct QuoteParams[]","name":"quoteParams","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"tokenToBeneficiary","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amountsToBeneficiary","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"excessToBeneficiary","type":"uint256"}],"name":"Flash","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Payback","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"beneficiary","type":"address"}],"name":"SetBeneficiary","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"defaultScaledOfferFactor","type":"uint32"}],"name":"SetDefaultScaledOfferFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IOracle","name":"oracle","type":"address"}],"name":"SetOracle","type":"event"},{"anonymous":false,"inputs":[{"components":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair","name":"quotePair","type":"tuple"},{"internalType":"uint32","name":"scaledOfferFactor","type":"uint32"}],"indexed":false,"internalType":"struct SwapperImpl.SetPairScaledOfferFactorParams[]","name":"params","type":"tuple[]"}],"name":"SetPairScaledOfferFactors","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"SetPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenToBeneficiary","type":"address"}],"name":"SetTokenToBeneficiary","type":"event"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultScaledOfferFactor","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct WalletImpl.Call[]","name":"calls_","type":"tuple[]"}],"name":"execCalls","outputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"bytes[]","name":"returnData","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair","name":"quotePair","type":"tuple"},{"internalType":"uint128","name":"baseAmount","type":"uint128"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct QuoteParams[]","name":"quoteParams_","type":"tuple[]"},{"internalType":"bytes","name":"callbackData_","type":"bytes"}],"name":"flash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair[]","name":"quotePairs_","type":"tuple[]"}],"name":"getPairScaledOfferFactors","outputs":[{"internalType":"uint32[]","name":"pairScaledOfferFactors","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"address","name":"tokenToBeneficiary","type":"address"},{"internalType":"contract IOracle","name":"oracle","type":"address"},{"internalType":"uint32","name":"defaultScaledOfferFactor","type":"uint32"},{"components":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair","name":"quotePair","type":"tuple"},{"internalType":"uint32","name":"scaledOfferFactor","type":"uint32"}],"internalType":"struct SwapperImpl.SetPairScaledOfferFactorParams[]","name":"pairScaledOfferFactors","type":"tuple[]"}],"internalType":"struct SwapperImpl.InitParams","name":"params_","type":"tuple"}],"name":"initializer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","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":"payback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary_","type":"address"}],"name":"setBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"defaultScaledOfferFactor_","type":"uint32"}],"name":"setDefaultScaledOfferFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOracle","name":"oracle_","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"}],"internalType":"struct QuotePair","name":"quotePair","type":"tuple"},{"internalType":"uint32","name":"scaledOfferFactor","type":"uint32"}],"internalType":"struct SwapperImpl.SetPairScaledOfferFactorParams[]","name":"params_","type":"tuple[]"}],"name":"setPairScaledOfferFactors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused_","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenToBeneficiary_","type":"address"}],"name":"setTokenToBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapperFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenToBeneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.