Source Code
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BridgeWithFeeLifi
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { IERC20 } from "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
interface IXCareConstants {
function sendFeeBps() external view returns (uint256);
function feeSendRecipient() external view returns (address);
}
contract BridgeWithFeeLifi {
IXCareConstants public immutable constants;
address public immutable LIFI_DIAMOND; // usually 0x1231... on most networks
event LifiExecuted(
address indexed user,
address indexed token,
uint256 amountIn,
uint256 feeAmount,
uint256 netAmount,
address approvalAddress,
address target,
uint256 value
);
error CallFailed(bytes returndata);
constructor(address _constants, address _lifiDiamond) {
require(_constants != address(0), "bad constants");
require(_lifiDiamond != address(0), "bad lifi");
constants = IXCareConstants(_constants);
LIFI_DIAMOND = _lifiDiamond;
}
/**
* @notice Backend computes LI.FI quote and passes:
* - approvalAddress: quote.estimate.approvalAddress
* - data: quote.transactionRequest.data
* - value: quote.transactionRequest.value (usually 0 for ERC20 routes)
* - (optional) target: quote.transactionRequest.to (commonly LiFiDiamond)
*
* IMPORTANT: you MUST validate off-chain that:
* - fromAddress is this contract
* - token/amount match what user provided
* - recipient/toAddress match your intended Solana address
*/
function bridgeWithFeeViaLifi(
address token,
uint256 amountIn,
address approvalAddress,
address target,
uint256 value,
bytes calldata data
) external payable {
require(amountIn > 0, "amount=0");
require(token != address(0), "token=0");
require(approvalAddress != address(0), "approval=0");
require(target != address(0), "target=0");
// Pull tokens
require(IERC20(token).transferFrom(msg.sender, address(this), amountIn), "pull failed");
// Fee
uint256 feeBps = constants.sendFeeBps();
address feeRecipient = constants.feeSendRecipient();
uint256 fee = (amountIn * feeBps) / 10_000;
uint256 netAmount = amountIn - fee;
require(netAmount > 0, "net=0");
require(IERC20(token).transfer(feeRecipient, fee), "fee transfer failed");
// Approve LI.FI's required spender for exactly netAmount
// (many tokens require reset-to-0 first)
require(IERC20(token).approve(approvalAddress, 0), "reset approve failed");
require(IERC20(token).approve(approvalAddress, netAmount), "approve failed");
// If LI.FI call needs native value (rare for ERC20 routes), forward it via msg.value
require(msg.value >= value, "insufficient msg.value");
(bool ok, bytes memory ret) = target.call{value: value}(data);
if (!ok) revert CallFailed(ret);
// refund any extra msg.value
uint256 refund = msg.value - value;
if (refund > 0) {
(bool r, ) = msg.sender.call{value: refund}("");
require(r, "refund failed");
}
emit LifiExecuted(msg.sender, token, amountIn, fee, netAmount, approvalAddress, target, value);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}{
"remappings": [
"@ensdomains/=lib/v4-core/node_modules/@ensdomains/",
"@openzeppelin/=lib/v4-core/lib/openzeppelin-contracts/",
"@uniswap/v4-core/=lib/v4-periphery/lib/v4-core/",
"ds-test/=lib/v4-core/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
"forge-std/=lib/v4-core/lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"hardhat/=lib/v4-core/node_modules/hardhat/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"permit2/=lib/permit2/",
"solmate/=lib/v4-core/lib/solmate/",
"v2-core/=lib/v2-core/contracts/",
"v3-core/=lib/v3-core/",
"v4-core/=lib/v4-core/src/",
"v4-periphery/=lib/v4-periphery/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "shanghai",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_constants","type":"address"},{"internalType":"address","name":"_lifiDiamond","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"returndata","type":"bytes"}],"name":"CallFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"approvalAddress","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LifiExecuted","type":"event"},{"inputs":[],"name":"LIFI_DIAMOND","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"approvalAddress","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"bridgeWithFeeViaLifi","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"constants","outputs":[{"internalType":"contract IXCareConstants","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c03461010457601f61097938819003918201601f19168301916001600160401b0383118484101761010857808492604094855283398101031261010457610052602061004b8361011c565b920161011c565b906001600160a01b031680156100cf576001600160a01b0382161561009f5760805260a0526040516108489081610131823960805181818161013e0152610708015260a051816107490152f35b60405162461bcd60e51b8152602060048201526008602482015267626164206c69666960c01b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c62616420636f6e7374616e747360981b6044820152606490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b03821682036101045756fe608080604052600436101561001c575b50361561001a575f80fd5b005b5f3560e01c908163020a1f7d146107375750806372de5b2f146106f35763e31b668b14610049575f61000f565b60c036600319011261059f576004356001600160a01b0381169081900361059f576024356044356001600160a01b03811680820361059f576064356001600160a01b038116919082810361059f576084359360a43567ffffffffffffffff811161059f573660238201121561059f57806004013567ffffffffffffffff811161059f57366024828401011161059f5787156106c3578815610694578415610662578515610632576040516323b872dd60e01b8152336004820152306024820152604481018990526020816064815f8e5af1908115610462575f91610613575b50156105e05760405163314b135960e21b8152937f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316602086600481845afa958615610462575f966105ab575b509460206004966040519788809263de83bf0f60e01b82525afa958615610462575f96610563575b50808a02908a82040361054f576127109004936101c2858b6107c6565b9586156105225760405163a9059cbb60e01b81526001600160a01b039091166004820152602481018690526020818d815f816044810103925af1908115610462575f91610503575b50156104c8575f60208c60446040518094819363095ea7b360e01b83528d60048401528160248401525af1908115610462575f916104a9575b501561046d5760405163095ea7b360e01b81526001600160a01b03919091166004820152602481018690526020816044815f8f5af1908115610462575f91610433575b50156103fd578734106103bf576024885f94848695604051948593018337810185815203925af16102b56107d3565b901561036557506102c685346107c6565b80610314575b50604051958652602086015260408501526060840152608083015260a08201527f9e1325fc0dca5fa245a38c089a535cae705d2298cbd549581bf0815d03d454f760c03392a3005b5f80808093335af16103246107d3565b5015610330575f6102cc565b60405162461bcd60e51b815260206004820152600d60248201526c1c99599d5b990819985a5b1959609a1b6044820152606490fd5b6040519063a5fa8d2b60e01b825260206004830152818151918260248301525f5b8381106103a7575050815f6044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001610386565b60405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e74206d73672e76616c756560501b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd994819985a5b195960921b6044820152606490fd5b610455915060203d60201161045b575b61044d8183610778565b8101906107ae565b5f610286565b503d610443565b6040513d5f823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152731c995cd95d08185c1c1c9bdd994819985a5b195960621b6044820152606490fd5b6104c2915060203d60201161045b5761044d8183610778565b5f610243565b60405162461bcd60e51b8152602060048201526013602482015272199959481d1c985b9cd9995c8819985a5b1959606a1b6044820152606490fd5b61051c915060203d60201161045b5761044d8183610778565b5f61020a565b60405162461bcd60e51b815260206004820152600560248201526406e65743d360dc1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b9095506020813d6020116105a3575b8161057f60209383610778565b8101031261059f57516001600160a01b038116810361059f57945f6101a5565b5f80fd5b3d9150610572565b95506020863d6020116105d8575b816105c660209383610778565b8101031261059f57945194602061017d565b3d91506105b9565b60405162461bcd60e51b815260206004820152600b60248201526a1c1d5b1b0819985a5b195960aa1b6044820152606490fd5b61062c915060203d60201161045b5761044d8183610778565b5f610128565b60405162461bcd60e51b815260206004820152600860248201526707461726765743d360c41b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a6024820152690617070726f76616c3d360b41b6044820152606490fd5b60405162461bcd60e51b81526020600482015260076024820152660746f6b656e3d360cc1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152670616d6f756e743d360c41b6044820152606490fd5b3461059f575f36600319011261059f576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461059f575f36600319011261059f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b90601f8019910116810190811067ffffffffffffffff82111761079a57604052565b634e487b7160e01b5f52604160045260245ffd5b9081602091031261059f5751801515810361059f5790565b9190820391821161054f57565b3d1561080d573d9067ffffffffffffffff821161079a5760405191610802601f8201601f191660200184610778565b82523d5f602084013e565b60609056fea2646970667358221220f5fa90ab25225d0d7bb0d8e2e5652809ce64fadf1a20ebc05b530538d74c55af64736f6c634300081c0033000000000000000000000000890ed658905efbaeed77069760ec9c7a62abef020000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae
Deployed Bytecode
0x608080604052600436101561001c575b50361561001a575f80fd5b005b5f3560e01c908163020a1f7d146107375750806372de5b2f146106f35763e31b668b14610049575f61000f565b60c036600319011261059f576004356001600160a01b0381169081900361059f576024356044356001600160a01b03811680820361059f576064356001600160a01b038116919082810361059f576084359360a43567ffffffffffffffff811161059f573660238201121561059f57806004013567ffffffffffffffff811161059f57366024828401011161059f5787156106c3578815610694578415610662578515610632576040516323b872dd60e01b8152336004820152306024820152604481018990526020816064815f8e5af1908115610462575f91610613575b50156105e05760405163314b135960e21b8152937f000000000000000000000000890ed658905efbaeed77069760ec9c7a62abef026001600160a01b0316602086600481845afa958615610462575f966105ab575b509460206004966040519788809263de83bf0f60e01b82525afa958615610462575f96610563575b50808a02908a82040361054f576127109004936101c2858b6107c6565b9586156105225760405163a9059cbb60e01b81526001600160a01b039091166004820152602481018690526020818d815f816044810103925af1908115610462575f91610503575b50156104c8575f60208c60446040518094819363095ea7b360e01b83528d60048401528160248401525af1908115610462575f916104a9575b501561046d5760405163095ea7b360e01b81526001600160a01b03919091166004820152602481018690526020816044815f8f5af1908115610462575f91610433575b50156103fd578734106103bf576024885f94848695604051948593018337810185815203925af16102b56107d3565b901561036557506102c685346107c6565b80610314575b50604051958652602086015260408501526060840152608083015260a08201527f9e1325fc0dca5fa245a38c089a535cae705d2298cbd549581bf0815d03d454f760c03392a3005b5f80808093335af16103246107d3565b5015610330575f6102cc565b60405162461bcd60e51b815260206004820152600d60248201526c1c99599d5b990819985a5b1959609a1b6044820152606490fd5b6040519063a5fa8d2b60e01b825260206004830152818151918260248301525f5b8381106103a7575050815f6044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001610386565b60405162461bcd60e51b8152602060048201526016602482015275696e73756666696369656e74206d73672e76616c756560501b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d185c1c1c9bdd994819985a5b195960921b6044820152606490fd5b610455915060203d60201161045b575b61044d8183610778565b8101906107ae565b5f610286565b503d610443565b6040513d5f823e3d90fd5b60405162461bcd60e51b81526020600482015260146024820152731c995cd95d08185c1c1c9bdd994819985a5b195960621b6044820152606490fd5b6104c2915060203d60201161045b5761044d8183610778565b5f610243565b60405162461bcd60e51b8152602060048201526013602482015272199959481d1c985b9cd9995c8819985a5b1959606a1b6044820152606490fd5b61051c915060203d60201161045b5761044d8183610778565b5f61020a565b60405162461bcd60e51b815260206004820152600560248201526406e65743d360dc1b6044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b9095506020813d6020116105a3575b8161057f60209383610778565b8101031261059f57516001600160a01b038116810361059f57945f6101a5565b5f80fd5b3d9150610572565b95506020863d6020116105d8575b816105c660209383610778565b8101031261059f57945194602061017d565b3d91506105b9565b60405162461bcd60e51b815260206004820152600b60248201526a1c1d5b1b0819985a5b195960aa1b6044820152606490fd5b61062c915060203d60201161045b5761044d8183610778565b5f610128565b60405162461bcd60e51b815260206004820152600860248201526707461726765743d360c41b6044820152606490fd5b60405162461bcd60e51b815260206004820152600a6024820152690617070726f76616c3d360b41b6044820152606490fd5b60405162461bcd60e51b81526020600482015260076024820152660746f6b656e3d360cc1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152670616d6f756e743d360c41b6044820152606490fd5b3461059f575f36600319011261059f576040517f000000000000000000000000890ed658905efbaeed77069760ec9c7a62abef026001600160a01b03168152602090f35b3461059f575f36600319011261059f577f0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae6001600160a01b03168152602090f35b90601f8019910116810190811067ffffffffffffffff82111761079a57604052565b634e487b7160e01b5f52604160045260245ffd5b9081602091031261059f5751801515810361059f5790565b9190820391821161054f57565b3d1561080d573d9067ffffffffffffffff821161079a5760405191610802601f8201601f191660200184610778565b82523d5f602084013e565b60609056fea2646970667358221220f5fa90ab25225d0d7bb0d8e2e5652809ce64fadf1a20ebc05b530538d74c55af64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000890ed658905efbaeed77069760ec9c7a62abef020000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae
-----Decoded View---------------
Arg [0] : _constants (address): 0x890ed658905EFbaeeD77069760Ec9c7a62aBEF02
Arg [1] : _lifiDiamond (address): 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000890ed658905efbaeed77069760ec9c7a62abef02
Arg [1] : 0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae
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.