编译器
0.8.27+commit.40a35a09
文件 1 的 6:AbachiRedemption.sol
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
contract AbachiRedemption is Ownable {
using Address for address;
IERC20 public ABI;
IERC20 public USDC;
bool public paused = false;
uint256 public swapRatio = 23;
uint256 public constant RATIO_DIVISOR = 10;
uint8 public constant USDC_DECIMALS = 6;
uint8 public constant ABI_DECIMALS = 18;
event Swap(address indexed sender, address indexed recipient, uint256 amountABI, uint256 amountUSDC);
event RatioUpdated(uint256 newRatio);
event RecoveredUSDC(address indexed recipient, uint256 amount);
constructor(address _ABI, address _USDC) Ownable(msg.sender) {
ABI = IERC20(_ABI);
USDC = IERC20(_USDC);
}
function pause() external onlyOwner {
require(!paused, "Contract already paused");
paused = true;
}
function unpause() external onlyOwner {
require(paused, "Contract is not paused");
paused = false;
}
function setSwapRatio(uint256 _newRatio) external onlyOwner {
require(_newRatio > 0, "Ratio must be greater than zero");
swapRatio = _newRatio;
emit RatioUpdated(_newRatio);
}
function swap() external {
uint256 balance = ABI.balanceOf(msg.sender);
_swapFor(msg.sender, balance);
}
function swapFor(address _recipient, uint256 _amount) external {
_swapFor(_recipient, _amount);
}
function withdrawTo(address _recipient, uint256 _amount) external onlyOwner {
require(ABI.transfer(_recipient, _amount), "Failed to transfer ABI");
}
function recoverUSDC(uint256 _amount) external onlyOwner {
require(_amount > 0, "Amount must be greater than zero");
require(USDC.balanceOf(address(this)) >= _amount, "Insufficient USDC balance");
require(USDC.transfer(msg.sender, _amount), "Failed to transfer USDC");
emit RecoveredUSDC(msg.sender, _amount);
}
function calculateUSDC(uint256 _amount) external view returns (uint256) {
return (_amount * swapRatio * 10**USDC_DECIMALS) / (10**ABI_DECIMALS * RATIO_DIVISOR);
}
function setUSDC(address _usdc) external onlyOwner {
USDC = IERC20(_usdc);
}
function setABI(address _abi) external onlyOwner {
ABI = IERC20(_abi);
}
function _swapFor(address _recipient, uint256 _amount) private {
require(!paused, "Contract is paused");
require(_amount > 0, "Invalid ABI amount");
uint256 usdcAmount = (_amount * swapRatio * 10**USDC_DECIMALS) / (10**ABI_DECIMALS * RATIO_DIVISOR);
require(ABI.transferFrom(msg.sender, address(this), _amount), "Failed to transfer ABI");
require(USDC.transfer(_recipient, usdcAmount), "Failed to transfer USDC");
emit Swap(msg.sender, _recipient, _amount, usdcAmount);
}
}
文件 2 的 6:Address.sol
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
library Address {
error AddressEmptyCode(address target);
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}
文件 3 的 6:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 4 的 6:Errors.sol
pragma solidity ^0.8.20;
library Errors {
error InsufficientBalance(uint256 balance, uint256 needed);
error FailedCall();
error FailedDeployment();
error MissingPrecompile(address);
}
文件 5 的 6:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 6 的 6:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/AbachiRedemption.sol": "AbachiRedemption"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_ABI","type":"address"},{"internalType":"address","name":"_USDC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"RatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RecoveredUSDC","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountABI","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountUSDC","type":"uint256"}],"name":"Swap","type":"event"},{"inputs":[],"name":"ABI","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ABI_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATIO_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"calculateUSDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_abi","type":"address"}],"name":"setABI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newRatio","type":"uint256"}],"name":"setSwapRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdc","type":"address"}],"name":"setUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"swapFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]