编译器
0.8.22+commit.4fc1097e
文件 1 的 11:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 11:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 11:DateTime.sol
pragma solidity 0.8.22;
library DateTime {
uint256 constant SECONDS_PER_DAY = 24 * 60 * 60;
uint256 constant SECONDS_PER_HOUR = 60 * 60;
uint256 constant SECONDS_PER_MINUTE = 60;
function getHour(uint256 _timestamp) private pure returns (uint256) {
uint256 secs = _timestamp % SECONDS_PER_DAY;
return secs / SECONDS_PER_HOUR;
}
function getMinute(uint256 _timestamp) private pure returns (uint256) {
uint256 secs = _timestamp % SECONDS_PER_HOUR;
return secs / SECONDS_PER_MINUTE;
}
function getSecond(uint256 _timestamp) private pure returns (uint256) {
return _timestamp % SECONDS_PER_MINUTE;
}
function subHours(uint256 _timestamp, uint256 _hours) private pure returns (uint256) {
return _timestamp - _hours * SECONDS_PER_HOUR;
}
function subMinutes(uint256 _timestamp, uint256 _minutes) private pure returns (uint256) {
return _timestamp - _minutes * SECONDS_PER_MINUTE;
}
function subSeconds(uint256 _timestamp, uint256 _seconds) private pure returns (uint256) {
return _timestamp - _seconds;
}
function getMidnightTimestamp(uint256 _timestamp) internal pure returns (uint256) {
uint256 midnightTimestap = subHours(_timestamp, getHour(_timestamp));
midnightTimestap = subMinutes(midnightTimestap, getMinute(_timestamp));
return subSeconds(midnightTimestap, getSecond(_timestamp));
}
}
文件 4 的 11:ERC20.sol
pragma solidity ^0.8.0;
import "../interfaces/IERC20.sol";
import "../extensions/IERC20Metadata.sol";
import "../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
文件 5 的 11:GenStructs.sol
pragma solidity 0.8.22;
struct UserData {
bool toBeClosed;
bytes32 identifier;
address owner;
address receiver;
address srcToken;
address dstToken;
uint8 tau;
uint40 exeRequired;
uint256 srcAmount;
uint256 limitOrderBuy;
}
struct UserDetail {
address receiver;
uint8 tau;
uint40 nextExecution;
uint40 lastExecution;
uint256 limitOrderBuy;
}
struct UserDca {
bool toBeClosed;
bytes32 identifier;
address srcToken;
address dstToken;
uint16 code;
uint40 dateCreation;
uint40 exeRequired;
uint40 exePerformed;
uint256 srcAmount;
}
struct ExeData {
uint8 onGoing;
uint8 errCount;
uint8 limitCount;
uint16 code;
uint40 dateCreation;
uint40 nextExecution;
uint40 lastExecution;
uint40 exePerformed;
uint256 fundTransferred;
}
struct ResolverData {
bool toBeClosed;
bool allowOk;
bool balanceOk;
address owner;
address receiver;
address srcToken;
address dstToken;
uint8 srcDecimals;
uint8 dstDecimals;
uint8 onGoing;
uint256 srcAmount;
uint256 limitOrderBuy;
}
struct StoredData {
uint256 timestamp;
uint256 tokenValue;
uint256 tokenAmount;
}
struct QueueData {
bytes32 identifier;
address owner;
address receiver;
address srcToken;
address dstToken;
uint8 tau;
uint40 exeRequired;
uint40 dateCreation;
uint40 nextExecution;
uint256 srcAmount;
uint256 limitOrderBuy;
}
文件 6 的 11:IERC20.sol
pragma solidity ^0.8.0;
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 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 7 的 11:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../interfaces/IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 8 的 11:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 9 的 11:INUI.sol
pragma solidity 0.8.22;
import { UserData } from "../lib/GenStructs.sol";
interface INUI {
function closePosition(bytes32 _identifier, address _user) external;
function updateAllowance(uint40 _id) external;
function totalDCAs() external view returns (uint40);
function userData(uint40 _id) external view returns (UserData memory);
function updatePositionPerExecution(uint40 _timeToDelete, uint40 _timeToUpdate) external;
function positionPerExecution(uint40) external view returns (uint40);
}
文件 10 的 11:NRI.sol
pragma solidity 0.8.22;
import { UserData, ExeData, ResolverData } from "./lib/GenStructs.sol";
import { ERC20 } from "./lib/ERC20.sol";
import { SafeERC20 } from "./utils/SafeERC20.sol";
import { INUI } from "./interfaces/INUI.sol";
import { DateTime } from "./lib/DateTime.sol";
error NotAuthorized();
error ExecutionNotRequired();
error EmergencyPause();
contract NRI {
using SafeERC20 for ERC20;
ExeData[] private dcaExeData;
mapping (bytes32 => uint40) private dcaPosition;
mapping (uint40 => uint40) private positionToChange;
mapping (uint40 => bool) private changeRequired;
bool public resolverRunning;
bool public operative;
uint40 public maxDcaExecutable;
uint24 constant private TIME_BASE = 1 days;
uint8 constant private ERROR_LIMIT = 2;
uint8 constant private LIMIT_ORDER_ERROR = 5;
address immutable public NUI;
address immutable public RESOLVER;
address immutable public ADMIN;
event PositionCompleted(address owner, bytes32 identifier);
event PositionClosedByError(address owner, bytes32 identifier);
event PositionClosedByLimitOrderLimit(address owner, bytes32 identifier);
event PositionClosedByQueue(address owner, bytes32 identifier);
modifier onlyResolver(){
if(msg.sender != RESOLVER) revert NotAuthorized();
_;
}
modifier onlyNUI(){
require(msg.sender == NUI, "Not Authorized");
_;
}
modifier onlyAdmin(){
require(msg.sender == ADMIN, "Not Authorized");
_;
}
modifier protocolOperative(){
if(!operative) revert EmergencyPause();
_;
}
constructor(address _NUI, address _resolver){
NUI = _NUI;
RESOLVER = _resolver;
ADMIN = msg.sender;
operative = true;
maxDcaExecutable = type(uint40).max;
}
function emergencyPause() external onlyAdmin {
operative = !operative;
}
function initMaxDcaExecutable() external onlyAdmin {
maxDcaExecutable = type(uint40).max;
}
function updateExecutionDate(bytes32 _identifier, uint8 _tau) external onlyNUI {
uint40 position = dcaPosition[_identifier];
uint40 newExeDate = _positionSlippage(dcaExeData[position].nextExecution, _tau);
INUI(NUI).updatePositionPerExecution(dcaExeData[position].nextExecution, newExeDate);
dcaExeData[position].nextExecution = newExeDate;
}
function createPosition(bytes32 _identifier, uint40 _nextExecution) external onlyNUI {
dcaPosition[_identifier] = INUI(NUI).totalDCAs();
_setExeData(uint40(block.timestamp), _nextExecution);
}
function closePosition(bytes32 _identifier, bytes32 _identifierLast) external onlyNUI {
if(_identifier != _identifierLast){
dcaExeData[dcaPosition[_identifier]] = dcaExeData[dcaPosition[_identifierLast]];
dcaPosition[_identifierLast] = dcaPosition[_identifier];
}
dcaPosition[_identifier] = 0;
dcaExeData.pop();
}
function snapsExecution() external onlyResolver protocolOperative {
resolverRunning = true;
}
function executionStart(uint40[] memory _id) external onlyResolver protocolOperative {
UserData memory userInfo;
uint40 length = uint40(_id.length);
uint256 initBalance;
if(!resolverRunning) resolverRunning = true;
for(uint40 i; i < length; ++i){
if(block.timestamp < dcaExeData[_id[i]].nextExecution || dcaExeData[_id[i]].onGoing > 0) continue;
if(changeRequired[_id[i]]) changeRequired[_id[i]] = false;
userInfo = INUI(NUI).userData(_id[i]);
dcaExeData[_id[i]].onGoing = 1;
if(!userInfo.toBeClosed){
initBalance = ERC20(userInfo.srcToken).balanceOf(RESOLVER);
ERC20(userInfo.srcToken).safeTransferFrom(userInfo.owner, RESOLVER, userInfo.srcAmount);
dcaExeData[_id[i]].fundTransferred = ERC20(userInfo.srcToken).balanceOf(RESOLVER) - initBalance;
}
}
}
function updatePositions(uint40[] memory _id, uint16[] memory _code) external onlyResolver protocolOperative {
UserData memory userInfo;
uint40 length = uint40(_id.length);
for(uint40 i; i < length; ++i){
if(block.timestamp < dcaExeData[_id[i]].nextExecution) continue;
userInfo = INUI(NUI).userData(_id[i]);
dcaExeData[_id[i]].onGoing = 2;
dcaExeData[_id[i]].lastExecution = dcaExeData[_id[i]].nextExecution;
dcaExeData[_id[i]].nextExecution = _generateNextExecution(dcaExeData[_id[i]].nextExecution, userInfo.tau);
dcaExeData[_id[i]].code = _code[i];
if(_code[i] == 200){
if (dcaExeData[_id[i]].errCount != 0) dcaExeData[_id[i]].errCount = 0;
if (dcaExeData[_id[i]].limitCount != 0) dcaExeData[_id[i]].limitCount = 0;
unchecked {
++dcaExeData[_id[i]].exePerformed;
}
INUI(NUI).updateAllowance(_id[i]);
}else{
unchecked {
_code[i] == 402 ? ++dcaExeData[_id[i]].limitCount : ++dcaExeData[_id[i]].errCount;
}
if(_code[i] != 999 && dcaExeData[_id[i]].fundTransferred != 0){
ERC20(userInfo.srcToken).safeTransferFrom(RESOLVER, userInfo.owner, dcaExeData[_id[i]].fundTransferred);
}
}
dcaExeData[_id[i]].fundTransferred = 0;
INUI(NUI).updatePositionPerExecution(dcaExeData[_id[i]].lastExecution, dcaExeData[_id[i]].nextExecution);
}
}
function executionCompletion(uint40[] memory _id, uint40 _maxDca) external onlyResolver protocolOperative {
UserData memory userInfo;
bool close;
uint40 length = uint40(_id.length);
uint40 id;
if(_maxDca != 0) maxDcaExecutable = _maxDca;
for(uint40 i; i < length; ++i){
id = _adjustPositionAfterDelete(changeRequired[_id[i]], _id[i], positionToChange[_id[i]]);
dcaExeData[id].onGoing = 0;
userInfo = INUI(NUI).userData(id);
if(dcaExeData[id].errCount >= ERROR_LIMIT){
close = true;
emit PositionClosedByError(userInfo.owner, userInfo.identifier);
}else if(dcaExeData[id].limitCount >= LIMIT_ORDER_ERROR){
close = true;
emit PositionClosedByLimitOrderLimit(userInfo.owner, userInfo.identifier);
}else if(userInfo.exeRequired > 0 && dcaExeData[id].exePerformed >= userInfo.exeRequired){
close = true;
emit PositionCompleted(userInfo.owner, userInfo.identifier);
}else if(userInfo.toBeClosed){
close = true;
emit PositionClosedByQueue(userInfo.owner, userInfo.identifier);
}
if(close){
close = false;
INUI(NUI).updatePositionPerExecution(dcaExeData[id].nextExecution, 0);
INUI(NUI).closePosition(userInfo.identifier, userInfo.owner);
positionToChange[INUI(NUI).totalDCAs()] = id;
changeRequired[INUI(NUI).totalDCAs()] = true;
}
}
if(resolverRunning) resolverRunning = false;
}
function positionDetail(bytes32 _identifier) external view onlyNUI returns (ExeData memory){
return dcaExeData[dcaPosition[_identifier]];
}
function amountExecutablePositions() external view onlyResolver returns (uint40){
uint40 totalpositions = INUI(NUI).totalDCAs();
uint40 executablePositions;
for(uint40 i; i < totalpositions; ++i){
if(block.timestamp >= dcaExeData[i].nextExecution || dcaExeData[i].onGoing > 0){
unchecked {
++executablePositions;
}
}
}
return executablePositions;
}
function executableIds(uint40 _amountExecutablePositions) external view onlyResolver returns (uint40[] memory){
uint40 totalpositions = INUI(NUI).totalDCAs();
uint40[] memory ids = new uint40[](_amountExecutablePositions);
uint40 idx;
for(uint40 i; i < totalpositions; ++i){
if(block.timestamp >= dcaExeData[i].nextExecution || dcaExeData[i].onGoing > 0){
ids[idx] = i;
unchecked {
++idx;
}
}
}
return ids;
}
function executionsDetail(uint40[] memory _id) external view onlyResolver returns (ResolverData[] memory){
uint40 length = uint40(_id.length);
UserData memory userInfo;
ResolverData[] memory resultData = new ResolverData[](length);
for(uint40 i; i < length; ++i){
userInfo = INUI(NUI).userData(_id[i]);
resultData[i] = ResolverData(
userInfo.toBeClosed,
ERC20(userInfo.srcToken).allowance(userInfo.owner, address(this)) >= userInfo.srcAmount,
ERC20(userInfo.srcToken).balanceOf(userInfo.owner) >= userInfo.srcAmount,
userInfo.owner,
userInfo.receiver,
userInfo.srcToken,
userInfo.dstToken,
ERC20(userInfo.srcToken).decimals(),
ERC20(userInfo.dstToken).decimals(),
dcaExeData[_id[i]].onGoing,
userInfo.srcAmount,
userInfo.limitOrderBuy
);
}
return resultData;
}
function amountTransfered(uint40 _id) external view onlyResolver returns (uint256){
return dcaExeData[_id].fundTransferred;
}
function _setExeData(
uint40 _dateCreation,
uint40 _nextExecution
) private {
dcaExeData.push(ExeData(
0,
0,
0,
0,
_dateCreation,
_nextExecution,
0,
0,
0
));
}
function _generateNextExecution(uint40 _baseExecution, uint8 _tau) private view returns (uint40){
uint40 timestamp = uint40(DateTime.getMidnightTimestamp(block.timestamp));
uint40 nextExecution = (timestamp - _baseExecution) >= TIME_BASE ? timestamp : _baseExecution;
return _positionSlippage(nextExecution, _tau);
}
function _positionSlippage(uint40 _nextExecution, uint8 _tau) private view returns (uint40) {
uint40 nextExecution = _nextExecution + (_tau * TIME_BASE);
if(INUI(NUI).positionPerExecution(nextExecution) + 1 > maxDcaExecutable){
nextExecution += TIME_BASE;
if(INUI(NUI).positionPerExecution(nextExecution) + 1 > maxDcaExecutable){
nextExecution += TIME_BASE;
if(INUI(NUI).positionPerExecution(nextExecution) + 1 > maxDcaExecutable){
nextExecution += (5 * TIME_BASE);
if(INUI(NUI).positionPerExecution(nextExecution) + 1 > maxDcaExecutable){
nextExecution += (7 * TIME_BASE);
if(INUI(NUI).positionPerExecution(nextExecution) + 1 > maxDcaExecutable){
nextExecution += (14 * TIME_BASE);
}
}
}
}
}
return nextExecution;
}
function _adjustPositionAfterDelete(bool _isRequired, uint40 currentPosition, uint40 newPosition) private pure returns (uint40){
return _isRequired ? newPosition : currentPosition;
}
}
文件 11 的 11:SafeERC20.sol
pragma solidity ^0.8.0;
import "../interfaces/IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "./Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
{
"compilationTarget": {
"contracts/NRI.sol": "NRI"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_NUI","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmergencyPause","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"PositionClosedByError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"PositionClosedByLimitOrderLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"PositionClosedByQueue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"PositionCompleted","type":"event"},{"inputs":[],"name":"ADMIN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NUI","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESOLVER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountExecutablePositions","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint40","name":"_id","type":"uint40"}],"name":"amountTransfered","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_identifier","type":"bytes32"},{"internalType":"bytes32","name":"_identifierLast","type":"bytes32"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_identifier","type":"bytes32"},{"internalType":"uint40","name":"_nextExecution","type":"uint40"}],"name":"createPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"_amountExecutablePositions","type":"uint40"}],"name":"executableIds","outputs":[{"internalType":"uint40[]","name":"","type":"uint40[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint40[]","name":"_id","type":"uint40[]"},{"internalType":"uint40","name":"_maxDca","type":"uint40"}],"name":"executionCompletion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40[]","name":"_id","type":"uint40[]"}],"name":"executionStart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40[]","name":"_id","type":"uint40[]"}],"name":"executionsDetail","outputs":[{"components":[{"internalType":"bool","name":"toBeClosed","type":"bool"},{"internalType":"bool","name":"allowOk","type":"bool"},{"internalType":"bool","name":"balanceOk","type":"bool"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint8","name":"srcDecimals","type":"uint8"},{"internalType":"uint8","name":"dstDecimals","type":"uint8"},{"internalType":"uint8","name":"onGoing","type":"uint8"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"limitOrderBuy","type":"uint256"}],"internalType":"struct ResolverData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initMaxDcaExecutable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxDcaExecutable","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operative","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_identifier","type":"bytes32"}],"name":"positionDetail","outputs":[{"components":[{"internalType":"uint8","name":"onGoing","type":"uint8"},{"internalType":"uint8","name":"errCount","type":"uint8"},{"internalType":"uint8","name":"limitCount","type":"uint8"},{"internalType":"uint16","name":"code","type":"uint16"},{"internalType":"uint40","name":"dateCreation","type":"uint40"},{"internalType":"uint40","name":"nextExecution","type":"uint40"},{"internalType":"uint40","name":"lastExecution","type":"uint40"},{"internalType":"uint40","name":"exePerformed","type":"uint40"},{"internalType":"uint256","name":"fundTransferred","type":"uint256"}],"internalType":"struct ExeData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resolverRunning","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"snapsExecution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_identifier","type":"bytes32"},{"internalType":"uint8","name":"_tau","type":"uint8"}],"name":"updateExecutionDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40[]","name":"_id","type":"uint40[]"},{"internalType":"uint16[]","name":"_code","type":"uint16[]"}],"name":"updatePositions","outputs":[],"stateMutability":"nonpayable","type":"function"}]