Contract Overview
Balance:
0 AVAX
Token:
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Source Code Verified (Exact Match)
Contract Name:
UniversalExchange
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; /** * @title StableCoin Interface * @dev StableCoin logic */ interface IStableCoin{ /** * @dev Transfer the specified _amount of tokens to the specified address. * Invokes the `tokenFallback` function if the recipient is a contract. * The token transfer fails if the recipient is a contract * but does not implement the `tokenFallback` function * or the fallback function to receive funds. * * @param _account Receiver address. * @param _amount Amount of tokens that will be transferred. * @param _data Transaction metadata. */ function transferWithData(address _account,uint256 _amount, bytes calldata _data ) external returns (bool success) ; /** * @dev Transfer the specified amount of tokens to the specified address. * This function works the same with the previous one * but doesn't contain `_data` param. * Added due to backwards compatibility reasons. * * @param _account Receiver address. * @param _amount Amount of tokens that will be transferred. */ function transfer(address _account, uint256 _amount) external returns (bool success); /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 _amount) external; /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address _account, uint256 _amount) external; /** * @dev mint the specified amount of tokens mint to the specified address. * @param _account Receiver address. * @param _amount Amount of tokens that will be transferred. */ function mint(address _account, uint256 _amount) external returns (bool); /** * @dev check balance * @param who new Address of property owners * @return balance of owner */ function balanceOf(address who) external view returns (uint256); /** * @dev allowance * @param owner Address of property owners * @param spender Address of spender * @return balance of allowance */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev transferFrom * @param from Address of property owners * @param to Address of spender * @param value token's value * @return success */ function transferFrom(address from, address to, uint256 value) external returns (bool); // function allowance( // address owner, // address spender // ) external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; interface IMarginLoan { /** * LoanStatus : it will have only follwoing three values. */ enum LoanStatus {NOTFOUND, PENDING, ACTIVE, COMPLETE, REJECT, CANCEL, PLEDGE} /** * MarginLoan: This struct will Provide the required field of Loan record */ struct MarginLoan { address user; address bank; uint256 loanAmount; uint256 interestRate; LoanStatus status; address tokenAddress; uint256 createdAt; uint256 installmentAmount; uint256 loanLimit; //maximum loan limit a user can avail against tokens uint256 loanPercentage; uint256 noOfTokens; } /** * LoanRequest: This event will triggered when ever their is request for loan */ event LoanRequest( address user, address bank, uint256 loanAmount, uint256 interestRate, LoanStatus status, address tokenAddress, uint256 createdAt, uint256 installmentAmount, uint256 id, uint256 loanPercentage, uint256 noOfTokens ); event UpdateLoan(address user, uint256 id, LoanStatus status); event PledgeToken(address user, address _token,uint256 noOfToekns, LoanStatus status); /** * called when user request loan from bank * */ function requestLoan( address _bank, uint256 _loanAmount, uint256 _interestRate, address _tokenAddress, uint256 createdAt, uint256 installmentAmount, uint256 _loanPercentage, uint256 noOfTokens ) external; /** * this function would return user margin with erc1400 address */ function getLoan(address _user, address tokenAddress) external view returns (uint256,uint256); function getPledgedLoan(address _user, address tokenAddress, address _bank) external view returns (uint256,uint256, uint256, uint256); /** * only user with a rule of bank can approve loan */ function completeLoan(address _user, uint256 _id) external returns (bool); function pledgeLoanToken(address _user,address _tokenAddress, address _bank) external returns (bool); /** *getLoanStatus: thsi function return loan status of address provided */ function getLoanStatus( address _user, uint256 _id ) external view returns (uint256); /** * only user with a rule of bank can reject loan */ function cancelLoan(uint256 _id) external returns (bool); /** * get t0tal of margin loan array of address */ function getTotalLoans(address _user) external view returns (uint256); /** * get total number of loan on a signle erc1400 token */ function getTotalLoanOfToken( address _user, address _token ) external view returns ( address[] memory, uint256[] memory, uint256[] memory, uint256[] memory ); function getTotalLoanOfPledgedToken(address _user, address _token, address _bank) external view returns ( address[] memory banks, uint256[] memory loanAmounts, uint256[] memory interestRates ); function getTotalNoOfTokens(address _user, address _token) external view returns (uint256[] memory,uint256[] memory); function getTotalNoOfPledgeTokens(address _user, address _token, address _bank) external view returns (uint256[] memory ids, uint256[] memory loans, uint256[] memory interest); function updateLoan( address user, uint256 id, uint256 amountPayed, uint256 caller ) external; function updatePledgeLoan( address user, uint256 id, uint256 amountPayed, uint256 tokensSold, uint256 caller ) external; function getLoanLimit(address user, address tokenAddress, uint256 loanPercentage) view external returns (uint256) ; function getRemainingLoanLimit( address user,address tokenAddress, uint256 loanPercentage) view external returns ( uint256); function addBlockedUser(address user) external ; function removeBlockedUser(address user) external; function isBlockedUser(address user) external view returns(bool); function payPledgeLoan(address user,address tokenAddress, address bank) external returns (bool); }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.19; /** * @title IAkruNFTAdminWhitelist */ interface IAkruNFTWhitelist { /** * @dev enum of different roles */ enum ROLES { unRegister,//0 superAdmin,//1 subSuperAdmin,//2 admin,//3 manager,//4 mediaManager,//5 propertyOwner,//6 propertyAccount,//7 propertyManager,//8 serviceProvider,//9 subServiceProvider,//10 bank,//11 user_USA,//12 user_Foreign //13 } function addWhitelistRole(address user, uint256 NFTId, ROLES role) external; function removeWhitelistedRole(address user, ROLES role) external; function addSuperAdmin() external; function updateAccreditationCheck(bool status) external; function isMediadManager(address _wallet) external view returns (bool); function addFeeAddress(address _feeAddress) external; function getFeeAddress() external view returns (address); function isAdmin(address _calle) external view returns (bool); function isSuperAdmin(address _calle) external view returns (bool); function isSubSuperAdmin(address _calle) external view returns (bool); function isBank(address _calle) external view returns (bool); function isOwner(address _calle) external view returns (bool); function isManager(address _calle) external view returns (bool); function getRoleInfo(uint256 id)external view returns (uint256 roleId,ROLES roleName,uint256 NFTID,address userAddress,uint256 idPrefix,bool valid); function checkUserRole(address userAddress, ROLES role) external view returns (bool); function setRoleIdPrefix(ROLES role, uint256 IdPrefix) external; function getRoleIdPrefix(ROLES role) external view returns (uint256); function addWhitelistUser(address _wallet,bool _kycVerified,bool _accredationVerified,uint256 _accredationExpiry,ROLES role,uint256 NFTId) external; function getWhitelistedUser(address _wallet)external view returns (address, bool, bool, uint256, ROLES, uint256, uint256, bool); function removeWhitelistedUser(address user, ROLES role) external; function updateKycWhitelistedUser(address _wallet,bool _kycVerified) external; function updateUserAccredationStatus(address _wallet,bool AccredationStatus) external; function updateAccredationWhitelistedUser(address _wallet, uint256 _accredationExpiry) external; function updateTaxWhitelistedUser(address _wallet,uint256 _taxWithholding) external; function addSymbols(string calldata _symbols) external returns (bool); function removeSymbols(string calldata _symbols) external returns (bool); function isKYCverfied(address user) external view returns (bool); function isAccreditationVerfied(address user) external view returns (bool); function isAccredatitationExpired(address user) external view returns (bool); function isUserUSA(address user) external view returns (bool); function isUserForeign(address user) external view returns (bool); function userType(address _caller) external view returns (bool); function getWhitelistInfo(address user)external view returns (bool valid,address wallet,bool kycVerified,bool accredationVerified,uint256 accredationExpiry,uint256 taxWithholding,ROLES role,uint256 userRoleId); function getUserRole(address _userAddress) external view returns (string memory, ROLES); function closeTokenismWhitelist() external; function isWhitelistedUser(address _userAddress) external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; interface ERC1820Registry { function setInterfaceImplementer( address _addr, bytes32 _interfaceHash, address _implementer ) external; function getInterfaceImplementer( address _addr, bytes32 _interfaceHash ) external view returns (address); function setManager(address _addr, address _newManager) external; function getManager(address _addr) external view returns (address); } /// Base client to interact with the registry. contract ERC1820Client { ERC1820Registry constant ERC1820REGISTRY = ERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); function setInterfaceImplementation( string memory interfaceLabel, address implementation ) internal { bytes32 interfaceHash = keccak256(abi.encodePacked(interfaceLabel)); ERC1820REGISTRY.setInterfaceImplementer( address(this), interfaceHash, implementation ); } function interfaceAddr( address addr, string memory interfaceLabel ) internal view returns (address) { bytes32 interfaceHash = keccak256(abi.encodePacked(interfaceLabel)); return ERC1820REGISTRY.getInterfaceImplementer(addr, interfaceHash); } function delegateManagement(address newManager) internal { ERC1820REGISTRY.setManager(address(this), newManager); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; /** * @title ERC1400RawERC20 * @dev ERC1400Raw with ERC20 retrocompatibility * @author AKRU's Dev team */ interface IERC1400RawERC20 { /** * ST0: Only admin is allowed * ST1: StableCoin: Cannot send tokens outside Tokenism * ST2: Only SuperAdmin is allowed * ST3: Invalid shares array provided * ST4: Transfer Blocked - Sender balance insufficient * ST5: Transfer Blocked - Sender not eligible * ST6: Transfer Blocked - Receiver not eligible * ST7: Transfer Blocked - Identity restriction * ST8: Percentages sum should be 100 * ST9: Only deployed by admin Or manager of Tokenism * ST10: Token Already exist with this Name * ST11: Token granularity can not be lower than 1 * ST12: Security Token: Cannot send tokens outside AKRU * ST13: Upgrade Yourself to Premium Account for more Buy * ST14: Whitelisting Failed * ST15: There is no space to new Investor * ST16: Only STO deployer set Cap ERC11400 Value and Once a time * ST17: Cap must be greater than 0 * ST18: Only Owner or Admin is allowed to send * ST19: There is no any Investor to distribute dividends * ST20: You did not have this much AKUSD * ST21: Not a contract address */ event TransferWithData( address indexed operator, address indexed from, address indexed to, uint256 value, bytes data, bytes operatorData ); event Issued(address indexed operator, address indexed to, uint256 value, bytes data, bytes operatorData); event Redeemed(address indexed operator, address indexed from, uint256 value, bytes data, bytes operatorData); event AuthorizedOperator(address indexed operator, address indexed tokenHolder); event RevokedOperator(address indexed operator, address indexed tokenHolder); /** * [ERC1400Raw INTERFACE (1/13)] * @dev Get the name of the token, e.g., "MyToken". * @return Name of the token. */ function name() external view returns (string memory); // 1/13 /** * [ERC1400Raw INTERFACE (2/13)] * @dev Get the symbol of the token, e.g., "MYT". * @return Symbol of the token. */ function symbol() external view returns (string memory); // 2/13 /** * [ERC1400Raw INTERFACE (3/13)] * @dev Get the total number of issued tokens. * @return Total supply of tokens currently in circulation. */ function totalSupply() external view returns (uint256); // 3/13 /** * [ERC1400Raw INTERFACE (4/13)] * @dev Get the balance of the account with address 'tokenHolder'. * @param tokenHolder Address for which the balance is returned. * @return Amount of token held by 'tokenHolder' in the token contract. */ function balanceOf(address tokenHolder) external view returns (uint256); // 4/13 /** * [ERC1400Raw INTERFACE (5/13)] * @dev Get the smallest part of the token that’s not divisible. * @return The smallest non-divisible part of the token. */ function granularity() external view returns (uint256); // 5/13 function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value)external returns (bool); /** * [ERC1400Raw INTERFACE (6/13)] * @dev Get the list of controllers as defined by the token contract. * @return List of addresses of all the controllers. */ function controllers() external view returns (address[] memory); // 6/13 function transferOwnership(address payable newOwner) external; /** * [ERC1400Raw INTERFACE (7/13)] * @dev Set a third party operator address as an operator of 'msg.sender' to transfer * and redeem tokens on its behalf. * @param operator Address to set as an operator for 'msg.sender'. */ function authorizeOperator(address operator) external; // 7/13 /** * [ERC1400Raw INTERFACE (8/13)] * @dev Remove the right of the operator address to be an operator for 'msg.sender' * and to transfer and redeem tokens on its behalf. * @param operator Address to rescind as an operator for 'msg.sender'. */ function revokeOperator(address operator) external; // 8/13 /** * [ERC1400Raw INTERFACE (9/13)] * @dev Indicate whether the operator address is an operator of the tokenHolder address. * @param operator Address which may be an operator of tokenHolder. * @param tokenHolder Address of a token holder which may have the operator address as an operator. * @return 'true' if operator is an operator of 'tokenHolder' and 'false' otherwise. */ function isOperator(address operator, address tokenHolder) external view returns (bool); // 9/13 /** * [ERC1400Raw INTERFACE (10/13)] * @dev Transfer the amount of tokens from the address 'msg.sender' to the address 'to'. * @param to Token recipient. * @param value Number of tokens to transfer. * @param data Information attached to the transfer, by the token holder. * [CONTAINS THE CONDITIONAL OWNERSHIP CERTIFICATE] */ function transferWithData(address to, uint256 value, bytes calldata data) external; // 10/13 /** * [ERC1400Raw INTERFACE (11/13)] * @dev Transfer the amount of tokens on behalf of the address 'from' to the address 'to'. * @param from Token holder (or 'address(0)' to set from to 'msg.sender'). * @param to Token recipient. * @param value Number of tokens to transfer. * @param data Information attached to the transfer, and intended for the token holder ('from'). * @param operatorData Information attached to the transfer by the operator. * [CONTAINS THE CONDITIONAL OWNERSHIP CERTIFICATE] */ function transferFromWithData(address from, address to, uint256 value, bytes calldata data, bytes calldata operatorData) external; // 11/13 /** * [ERC1400Raw INTERFACE (12/13)] * @dev Redeem the amount of tokens from the address 'msg.sender'. * @param value Number of tokens to redeem. * @param data Information attached to the redemption, by the token holder. * [CONTAINS THE CONDITIONAL OWNERSHIP CERTIFICATE] */ function redeem(uint256 value, bytes calldata data) external; // 12/13 /** * [ERC1400Raw INTERFACE (13/13)] * @dev Redeem the amount of tokens on behalf of the address from. * @param from Token holder whose tokens will be redeemed (or address(0) to set from to msg.sender). * @param value Number of tokens to redeem. * @param data Information attached to the redemption. * @param operatorData Information attached to the redemption, by the operator. * [CONTAINS THE CONDITIONAL OWNERSHIP CERTIFICATE] */ function redeemFrom(address from, uint256 value, bytes calldata data, bytes calldata operatorData) external; // 13/13 /** * [NOT MANDATORY FOR ERC1400Raw STANDARD] * @dev set property cap * @param propertyCap new property Cap. */ function cap(uint256 propertyCap) external; /** * @dev get basic cap * @return calculated cap */ function basicCap() external view returns (uint256); /** * @dev get all Users with there balance * @return all Users with there balance */ // function getStoredAllData(address adminAddress) external view returns (address[] memory, uint256[] memory); // function distributeDividends(address _token, uint256 _dividends) external; /** * [NOT MANDATORY FOR ERC1400Raw STANDARD] * @dev Issue the amout of tokens for the recipient 'to'. * @param to Token recipient. * @param value Number of tokens issued. * @param data Information attached to the issuance, by the token holder. * [CONTAINS THE CONDITIONAL OWNERSHIP CERTIFICATE] * @return A boolean that indicates if the operation was successful. */ function issue(address to, uint256 value, bytes calldata data) external returns (bool); /** * [NOT MANDATORY FOR ERC1400RawERC20 STANDARD][OVERRIDES ERC1400 METHOD] * @dev Migrate contract. * * ===> CAUTION: DEFINITIVE ACTION * * This function shall be called once a new version of the smart contract has been created. * Once this function is called: * - The address of the new smart contract is set in ERC1820 registry * - If the choice is definitive, the current smart contract is turned off and can never be used again * * @param newContractAddress Address of the new version of the smart contract. * @param definitive If set to 'true' the contract is turned off definitely. */ function migrate(address newContractAddress, bool definitive)external; /** * @dev close the ERC1400 smart contract */ function closeERC1400() external; /** * [NOT MANDATORY FOR ERC1400RawERC20 STANDARD]USED FOR DISTRIBUTION MODULE] * * ===> CAUTION: DEFINITIVE ACTION * * Once this function is called: * * @param _investor Address of the Investor. * @param _balance Balance of token listed on exchange. */ function addFromExchange(address _investor , uint256 _balance) external returns(bool); /** * [NOT MANDATORY FOR ERC1400RawERC20 STANDARD]USED FOR DISTRIBUTION MODULE] * * ===> CAUTION: DEFINITIVE ACTION * * Once this function is called: * * @param _investor Address of the Investor. * @param _balance Balance of token listed on exchange. */ function updateFromExchange(address _investor , uint256 _balance) external returns (bool); /** * @dev get all property owner of the property * @return _propertyOwners */ function propertyOwners() external view returns (address[] memory); /** * @dev get all property owner shares of the property * @return _shares */ function shares() external view returns (uint256[] memory); /** * @dev check if property owner exist in the property * @param _addr address of the user */ function isPropertyOwnerExist(address _addr) external view returns(bool isOwnerExist); /** * @dev toggleCertificateController activate/deactivate Certificate Controller * @param _isActive true/false */ function toggleCertificateController(bool _isActive) external; /** * @dev bulk mint of tokens to property owners exist in the property * @param to array of addresses of the owners * @param amount array of amount to be minted * @param cert array of certificate */ function bulkMint(address[] calldata to,uint256[] calldata amount,bytes calldata cert) external; /** * @dev add share percentages to property owners exist in the property * @param _shares array of shares of the owners * @param _owners array of addresses of the owners */ function addPropertyOwnersShares(uint256[] calldata _shares,address[] calldata _owners) external; /** * @dev to add token for distribution from exchange * @param _investor address of user * @param _balance balance of user * @return function call */ function addFromExchangeRaw1400(address _investor , uint256 _balance) external returns (bool); /** * @dev to update token for distribution from exchange * @param _investor address of user * @param _balance balance of user * @return function call */ function updateFromExchangeRaw1400(address _investor , uint256 _balance) external returns (bool); /** * @dev get whitelisted ERC1400 Address * @return address of whitlisting */ function getERC1400WhitelistAddress() external view returns (address); function reserveWallet() external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; import "../token/SecurityToken-US/ERC20/IERC1400RawERC20.sol"; // import "../whitelist/ITokenismWhitelist.sol"; import "./../NFTwhitelist/IAkruNFTWhitelist.sol"; import "../MarginLoan/IMarginLoan.sol"; import "../IStableCoin.sol"; interface IUniversalExchange { /** * E1: Only admin * E2: Only admin or whitelisted user * E3: Only admin or seller * E4: Only admin or buyer * E5: Only admin or seller or buyer * E6: Invalid Security Token address * E7: Price is zero * E8: Quantity is zero * E9: Insufficient Security Token balance * E10: Approve Security Tokens * E11: Invalid id * E12: Seller cannot buy there tokens * E13: Buy Quantity must be greater than zero * E14: Buy Quantity must be greater than Remaining Quantity * E15: Insufficient AKUSD balance or Not Allowed Balance * E16: Insufficient AKUSD allowance * E17: Seller cannot place Offer * E18: Price set by Buyer must be less than seller price * E19: Buyer already offered * E20: Wait for buyer counter * E21: No offers found * E22: Offer expired * E23: Price must be greater than buyer offer price * E24: Price must be smaller than listing price and Price must be greater than buyer offer price and Price must be lesser than previous offer price * E25: Price must be lesser than previous offer price * E26: Seller counter exceeded * E27: Remaing Quantity is must be greater or equal to offering quantity * E28: Wait for seller counter * E29: Price must be smaller than seller offer price and Greater than Buyer Offer Priced and Price must be smaller than listing price and Price must be greater than previous offer price * E30: Price must be greater than previous offer price * E31: Buyer counter exceeded * E32: Zero Address * E33: Incorrect Nonce * E34: Buyer cannot reject his counter * E35: Seller cannot reject his counter * E36: Unauthorized * E37: Buyer can't accept their own offer * E38: Seller can't accept their own offer * E39: Offer not Expire yet * E40: Invalid Signer or Incorrect Nonce * E41: Unable to transfer token(s) * E42: Token is Not Accepting on this Exchange * E43: Order Id is already Exist order ID should be unique */ enum Status { Default, // default value Listed, //for listings UnListed, //for Un listings Sold, // for offers and listings Created, // for offers Create Countered, // for on Counter Canceled, // for Cancelled Offer Rejected, //for Rejected Null, // for Not Exist more Expired // Expired Offer } struct Offers { uint128 buyerPrice; uint128 sellerPrice; uint256 expiryTime; uint128 quantity; uint256 buyerFeeAmount; address buyer; uint8 buyerCount; uint8 sellerCount; bool isOffered; bool isCallable; Status status; } struct ListTokens { uint128 price; uint128 quantity; uint128 remainingQty; uint128 tokenInHold; address seller; IERC1400RawERC20 token; Status status; bool isUsUSer; } event TokensListed( uint256 indexed id, uint128 price, uint128 quantity, address indexed seller, IERC1400RawERC20 indexed token ); event TokensPurchased( uint256 indexed id, uint128 quantity, uint128 price, address indexed seller, address indexed buyer, IERC1400RawERC20 token, address feeAddress, uint256 feeAmount ); event Counter( uint256 indexed id, uint128 quantity, uint128 price, address indexed seller, address indexed buyer, IERC1400RawERC20 token, uint256 buyerFee ); event ListingCanceled( uint256 indexed id, uint128 price, uint128 quantity, address indexed seller, IERC1400RawERC20 indexed token ); event RejectCounter( uint256 indexed id, uint128 quantity, uint128 price, address indexed seller, address indexed buyer, IERC1400RawERC20 token ); event BuyerOfferCanceled( uint256 indexed id, uint128 quantity, uint128 price, IERC1400RawERC20 token, address seller, address buyer ); event SellerOfferCanceled( uint256 indexed id, uint128 quantity, uint256 totalAmount, uint128 price, IERC1400RawERC20 token, address seller, address buyer ); event LoanPayed( uint256 totalAmount, IERC1400RawERC20 token, address seller, address bankAddress ); event OfferExpire( uint256 id, address buyer, uint256 totalAmount ); event UpdateStableCoin(address caller, address newStableCoin); event UpdateMarginLoan(address caller, address newMarginLoan); event UpdateWhiteListing(address caller, address whitelist); event SetFeeAddress(address caller, address newFeeAddress); event SetFeePercentage(address caller, uint128 newFeePercentage, string area); event ToggleMarginLoan(address caller, bool marginLoanStatus); event ToggleFee(address caller, bool feeStatus, string area); event SetExpiryDuration(address caller,uint256 expiryDuration); event IsExchangeForBoth(bool status, address sender); event TokenStatus(address caller, address token1, address token2,bool status); function sellTokens( uint128 price, uint128 quantity, uint256 orderId, IERC1400RawERC20 token ) external; function buyTokens(uint256 id, uint128 quantity) external; function buyerOffer( uint256 id, uint128 quantity, uint128 price ) external; function setFeeAddress(address newFeeAddress) external; function setFeePercentageUS(uint128 newFeePercentage) external; function setFeePercentageNonUS(uint128 newFeePercentage) external; function counterSeller( uint256 id, uint128 price, address buyer ) external; function counterBuyer( uint256 id, uint128 price, address buyer ) external; function cancelListing( uint256 id ) external; function rejectCounter( uint256 id, address buyer ) external; function getListings( uint256 id ) external view returns ( uint128 price, uint128 quantity, uint128 remainingQty, uint128 tokenInHold, IERC1400RawERC20 token, address seller, Status status ); function getOffer(address buyerWallet,uint256 id) external view returns ( uint128 buyerPrice, uint128 sellerPrice, uint256 expiryTime, uint128 quantity, address buyer, uint8 buyerCount, uint8 sellerCount, bool isOffered, bool isCallable, Status status ); function acceptCounter( uint256 id, address buyer ) external; function cancelBuyer( uint256 id ) external; function cancelSeller( uint256 id, address buyer ) external; function updateWhiteListing(IAkruNFTWhitelist newWhitelist) external; function updateStableCoin(IStableCoin newStableCoin) external; function updateMarginLoan(IMarginLoan newMarginLoan) external; // function updateInterfaceHash(string calldata interfaceHash) external; function toggleMarginLoan() external; function toggleFeeUS() external; function toggleFeeNonUS() external; function setExpiryDuration(uint256 newExpiryDuration) external; function expireOffer(uint256 id, address _wallet) external; function tokenStatus(address token, bool status) external; function tokenStatus(address token1,address token2, bool status) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19; import "./IUniversalExchange.sol"; import "../token/SecurityToken-US/ERC1820/ERC1820Client.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; /** * @title Universal Exchange * @author Umer Mubeen & Asadullah Khan * @notice Singleton Exchange Instance * @dev AKRU Exchange Smart Contract for Secondary Market */ contract UniversalExchange is IUniversalExchange, ERC1820Client, ReentrancyGuard { // using Counters for Counters.Counter; // Counters.Counter public count; mapping(uint256 => bool) public isOrderExist; IStableCoin public stableCoin; IAkruNFTWhitelist public whitelist; IMarginLoan public marginLoan; address public feeAddress; // uint256 public feePercentage; // in wei //Set Percentage of US and Non US fee Address uint256 public feePercentageUS; // in wei uint256 public feePercentageNonUS; // in wei // string public erc1400InterfaceId = "ERC20Token"; bool public marginLoanStatus = false; // bool public feeStatus = false; // Add for seperation of US and Non US Fee Status bool public feeStatusUS = false; bool public feeStatusNonUS = false; uint256 public expiryDuration = 10 minutes; // for production set 2 days ///@dev listing id to listing detail mapping(uint256 => ListTokens) private listedTokens; ///@dev offeror address to listing id to offer detail mapping(address => mapping(uint256 => Offers)) private listingOffers; ///@dev listing id to array of offeror address mapping(uint256 => address[]) public counterAddresses; ///@dev Tokens accepting for sale. mapping(address => bool) public isTokenAccepted; bool public isOpenForBoth; constructor( IStableCoin stableCoinAddress, IAkruNFTWhitelist whitelistingAddress, IMarginLoan marginLoanAddress ) { stableCoin = stableCoinAddress; whitelist = whitelistingAddress; marginLoan = marginLoanAddress; } function _onlyAdmin() private view { require(whitelist.isAdmin(msg.sender), "E1"); } function _onlyAdminAndUser() private view { require( whitelist.isAdmin(msg.sender) || whitelist.isWhitelistedUser(msg.sender) <= 200, "E2" ); } function _onlyAdminAndSeller(uint256 id) private view { ListTokens memory listing = listedTokens[id]; require( whitelist.isAdmin(msg.sender) || listing.seller == msg.sender, "E3" ); } function _onlyAdminAndBuyer(uint id) private view { require( whitelist.isAdmin(msg.sender) || listingOffers[msg.sender][id].buyer == msg.sender, "E4" ); } function _onlyAdminAndSellerAndBuyer(uint id) private view { ListTokens memory listing = listedTokens[id]; Offers memory listingOffer = listingOffers[msg.sender][id]; require( whitelist.isAdmin(msg.sender) || listing.seller == msg.sender || listingOffer.buyer == msg.sender, "E5" ); } modifier onlyAdmin() { _onlyAdmin(); _; } modifier onlyAdminAndUser() { _onlyAdminAndUser(); _; } modifier onlyAdminAndSeller(uint256 id) { _onlyAdminAndSeller(id); _; } modifier onlyAdminAndBuyer(uint256 id) { _onlyAdminAndBuyer(id); _; } modifier onlyAdminAndSellerAndBuyer(uint256 id) { _onlyAdminAndSellerAndBuyer(id); _; } /** * @dev List Token of any Property on Exchange for Sell * @param price: Price of Token that want on sell * @param quantity: Quantity of token that want to sell * @param token: Address of ERC1400/Security token */ function sellTokens( uint128 price, uint128 quantity, uint256 orderId, IERC1400RawERC20 token ) external override nonReentrant onlyAdminAndUser { require(isTokenAccepted[address(token)], "E42"); require(!isOrderExist[orderId],"E43"); require(price > 0 && quantity > 0 , "E7"); require(quantity <= token.balanceOf(msg.sender), "E9"); require(quantity <= token.allowance(msg.sender, address(this)), "E10"); bool usUser; if(whitelist.isUserForeign(msg.sender)){ usUser = false; }else{ usUser = true; } listedTokens[orderId] = ListTokens({ seller: msg.sender, token: token, price: price, quantity: quantity, remainingQty: quantity, tokenInHold: 0, status: Status.Listed, isUsUSer: usUser }); // count.increment(); token.addFromExchange(msg.sender, quantity); require(token.transferFrom(msg.sender, address(this), quantity),"E41"); emit TokensListed(orderId, price, quantity, msg.sender, token); } /** * @dev Buyer Direct Buy Token on that price. * @param quantity : number of tokens. * @param id: listed tokens id. */ function buyTokens( uint256 id, uint128 quantity ) external override onlyAdminAndUser nonReentrant { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); require(listing.seller != msg.sender, "E12"); require(quantity > 0, "E13"); require(quantity <= listing.remainingQty, "E14"); if(!isOpenForBoth){ require(whitelist.isUserForeign(msg.sender) != listing.isUsUSer,"Only Related User Purchase Token"); } uint256 totalAmount = quantity * listing.price; uint256 feeAmount = 0 ; if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = (totalAmount * feePercentageUS) / 100 ether; totalAmount = totalAmount +feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = (totalAmount * feePercentageNonUS) / 100 ether; totalAmount = totalAmount + feeAmount; } listing.remainingQty -= quantity; IERC1400RawERC20 token = listing.token; uint128 price = listing.price; if (listing.remainingQty == 0 && listing.tokenInHold == 0) { listing.status = Status.Sold; } if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = (totalAmount * feePercentageUS) / 1000 ether; totalAmount += feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = (totalAmount * feePercentageNonUS) / 100 ether; totalAmount = totalAmount + feeAmount; } require(stableCoin.balanceOf(msg.sender) >= totalAmount && stableCoin.allowance(msg.sender, address(this)) >= totalAmount, "E15"); require(stableCoin.transferFrom(msg.sender, address(this), totalAmount),"E41"); if (feeStatusUS || feeStatusNonUS) { // If fee Status is on then transfer fee to fee address require(stableCoin.transfer(feeAddress, feeAmount *2),"E41"); totalAmount -= feeAmount * 2; } if (marginLoanStatus) { uint256 payToSeller = adjustLoan( address(listing.token), listing.seller, totalAmount ); totalAmount = payToSeller; } if (totalAmount != 0) { require(stableCoin.transfer(listing.seller, totalAmount),"E41"); } require(token.transfer(msg.sender, quantity),"E41"); token.updateFromExchange(listing.seller, quantity); ///@dev null all offers made on this listing. nullOffer(id); emit TokensPurchased(id, quantity, price, listing.seller,msg.sender, token, feeAddress, feeAmount*2); } /** * @dev Send Offer for Purchase Token * @param id: listing id or order id of that token * @param quantity: Quantity of token that want to purchase * @param price: price that want to offer */ function buyerOffer( uint256 id, uint128 quantity, uint128 price ) external override onlyAdminAndUser { require(quantity > 0, "E8"); ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); require(listing.seller != msg.sender, "E17"); require(price < listing.price, "E18"); require(!listingOffers[msg.sender][id].isOffered, "E19"); require(quantity <= listing.remainingQty, "E14"); if(!isOpenForBoth){ require(whitelist.isUserForeign(msg.sender) != listing.isUsUSer,"Only Related User Purchase Token"); } uint256 totalAmount = quantity * price; uint256 feeAmount; if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = (totalAmount * feePercentageUS) / 100 ether; totalAmount = totalAmount +feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = (totalAmount * feePercentageNonUS) / 100 ether; totalAmount = totalAmount + feeAmount; } require(stableCoin.balanceOf(msg.sender) >= totalAmount && totalAmount <= stableCoin.allowance(msg.sender, address(this)), "E15"); listingOffers[msg.sender][id] = Offers({ buyerPrice: price, sellerPrice: listing.price, quantity: quantity, buyerFeeAmount:feeAmount, expiryTime: block.timestamp + expiryDuration, isOffered: true, buyerCount: 1, sellerCount: 0, isCallable: true, status: Status.Created, buyer: msg.sender }); counterAddresses[id].push(msg.sender); require(stableCoin.transferFrom(msg.sender, address(this), totalAmount),"E41"); emit Counter(id, quantity, price, listing.seller,msg.sender,listing.token, feeAmount); } /** * @dev Counter on buyer offer by seller * @param id: listing id or order id of that token * @param price: price that want to offer * @param buyer: Address of buyer whose want to buy token */ function counterSeller( uint256 id, uint128 price, address buyer ) external override onlyAdminAndSeller(id) { ListTokens storage listing = listedTokens[id]; Offers storage listingOffer = listingOffers[buyer][id]; require(listing.status == Status.Listed && (listingOffer.status == Status.Created || listingOffer.status == Status.Countered), "E11/E21"); require(listingOffer.isCallable, "E20"); require(msg.sender == listing.seller, "E40"); require(block.timestamp < listingOffer.expiryTime, "E22"); require(price > listingOffer.buyerPrice && price < listing.price && price < listingOffer.sellerPrice, "E23"); require(listingOffer.sellerCount < 2, "E26"); if (listingOffer.sellerCount < 1) { require(listingOffer.quantity <= listing.remainingQty, "E27"); listing.remainingQty -= listingOffer.quantity; listing.tokenInHold += listingOffer.quantity; } listingOffer.status = Status.Countered; listingOffer.sellerPrice = price; listingOffer.sellerCount++; listingOffer.isCallable = false; listingOffer.expiryTime = block.timestamp + expiryDuration; emit Counter(id, listingOffer.quantity, price, listing.seller,buyer,listing.token, 0); } /** * @dev Counter on seller offer by Buyer * @param id: listing id or order id of that token * @param price: price that want to offer */ function counterBuyer( uint256 id, uint128 price, address seller ) external override onlyAdminAndBuyer(id) { ListTokens memory listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); Offers storage listingOffer = listingOffers[seller][id]; require(!listingOffer.isCallable, "E28"); require( listingOffer.status == Status.Created || listingOffer.status == Status.Countered, "E21" ); require(block.timestamp < listingOffer.expiryTime, "E22"); require(price < listing.price && price < listingOffer.sellerPrice && price > listingOffer.buyerPrice, "E29"); require(listingOffer.buyerCount < 2, "E31"); uint256 priceDiff = price - listingOffer.buyerPrice; priceDiff *= listingOffer.quantity; uint256 feeAmount; if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = (priceDiff * feePercentageUS) / 100 ether; priceDiff = priceDiff +feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = (priceDiff * feePercentageNonUS) / 100 ether; priceDiff = priceDiff + feeAmount; } require(stableCoin.allowance(msg.sender, address(this)) >= priceDiff, "E16"); listingOffer.status = Status.Countered; listingOffer.buyerPrice = price; listingOffer.buyerCount++; listingOffer.isCallable = true; listingOffer.expiryTime = block.timestamp + expiryDuration; listingOffer.buyerFeeAmount += feeAmount; require(stableCoin.transferFrom(msg.sender, address(this), priceDiff),"E41"); emit Counter(id, listingOffer.quantity, price,listing.seller, msg.sender,listing.token, feeAmount); } /** * @dev Cancel the listing on exchange and return tokens to owner account. * @param id: it is the listing tokens id. */ function cancelListing( uint256 id ) external override onlyAdminAndSeller(id) nonReentrant { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); require(msg.sender == listing.seller, "E40"); listing.status = Status.UnListed; listing.token.updateFromExchange(listing.seller, listing.remainingQty+listing.tokenInHold); require(listing.token.transfer(listing.seller, listing.remainingQty + listing.tokenInHold),"E41"); listing.remainingQty = 0; listing.tokenInHold =0; nullOffer(id); emit ListingCanceled(id, listing.price, listing.remainingQty, listing.seller, listing.token); } /** * @dev null all the open offers and return the akusd to owners. * @param id: it is the listing tokens id. */ function nullOffer(uint256 id) private { uint256 len = counterAddresses[id].length; for (uint256 i = 0; i < len; ) { Offers storage counteroffers = listingOffers[counterAddresses[id][i]][id]; ListTokens memory listing = listedTokens[id]; if( counteroffers.quantity > listing.remainingQty + listing.tokenInHold && counteroffers.status == Status.Created) { address buyer = counterAddresses[id][i]; uint256 price = counteroffers.buyerPrice; uint256 quantity = counteroffers.quantity; uint256 totalAmount = (quantity * price) + counteroffers.buyerFeeAmount; counteroffers.status = Status.Null; delete counterAddresses[id][i]; require(stableCoin.transfer(buyer, totalAmount),"E41"); } unchecked { ++i; } } } /** * @dev get single listing * @param id: listing id * @return price ,quantity,remainingQty,tokenInHold,token,seller,status */ function getListings( uint256 id ) external view override returns ( uint128 price, uint128 quantity, uint128 remainingQty, uint128 tokenInHold, IERC1400RawERC20 token, address seller, Status status ) { ListTokens storage listing = listedTokens[id]; return ( listing.price, listing.quantity, listing.remainingQty, listing.tokenInHold, listing.token, listing.seller, listing.status ); } /** * * @dev Check offer by sending address of buyer and Id on which they send offer * @param buyerWallet address of buyer wallet * @param id Id on which buyer put offer * @return buyerPrice Price that offer by buyer * @return sellerPrice Price of seller * @return expiryTime Expiry time of that offer * @return quantity Quantity of Token on which they offered * @return buyer address of buyer * @return buyerCount number of counter buyer did * @return sellerCount number of counter seller did * @return isOffered check isOffered or not * @return isCallable is callable by the buyer * @return status status of this offer */ function getOffer(address buyerWallet,uint256 id) external view override returns ( uint128 buyerPrice, uint128 sellerPrice, uint256 expiryTime, uint128 quantity, address buyer, uint8 buyerCount, uint8 sellerCount, bool isOffered, bool isCallable, Status status ) { Offers storage listingOffer = listingOffers[buyerWallet][id]; return ( listingOffer.buyerPrice, listingOffer.sellerPrice, listingOffer.expiryTime, listingOffer.quantity, listingOffer.buyer, listingOffer.buyerCount, listingOffer.sellerCount, listingOffer.isOffered, listingOffer.isCallable, listingOffer.status ); } /** * @dev Reject Counter By Seller or Buyer. * @param buyer: address of buyer of tokens. * @param id: offers id of struct maping. */ function rejectCounter( uint256 id, address buyer ) external override onlyAdminAndSellerAndBuyer(id) { ListTokens storage listing = listedTokens[id]; Offers storage listingOffer = listingOffers[buyer][id]; require(listing.status == Status.Listed, "E11"); require(listingOffer.status == Status.Created || listingOffer.status == Status.Countered, "E21"); if (msg.sender == listing.seller) { require(listingOffer.isCallable, "E35"); } else if(msg.sender == buyer) { require(!listingOffer.isCallable, "E34"); } else { revert("E36"); } uint128 price = listingOffer.buyerPrice; uint128 quantity = listingOffer.quantity; uint256 totalAmount = (quantity * (price)) + listingOffer.buyerFeeAmount; if (listingOffer.sellerCount >= 1) { listing.remainingQty += listingOffer.quantity; listing.tokenInHold -= listingOffer.quantity; } listingOffer.status = Status.Rejected; require(stableCoin.transfer(buyer, totalAmount),"E41"); emit RejectCounter(id, quantity, price, listing.seller,buyer,listing.token); } /** * @dev Buyer or Seller Accept Counter * @param id: listing id or order id of that token */ function acceptCounter( uint256 id, address buyer ) external override onlyAdminAndSellerAndBuyer(id) nonReentrant { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); Offers storage listingOffer = listingOffers[buyer][id]; require( listingOffer.status == Status.Created || listingOffer.status == Status.Countered, "E21" ); uint128 price = 0; uint128 quantity = listingOffer.quantity; uint256 feeAmount = 0; if (msg.sender == buyer) { require(!listingOffer.isCallable, "E37"); uint256 priceDiff = listingOffer.sellerPrice - listingOffer.buyerPrice; priceDiff *= quantity; if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = (priceDiff *feePercentageUS)/100 ether; priceDiff = priceDiff + feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = (priceDiff *feePercentageNonUS)/100 ether; priceDiff = priceDiff + feeAmount; } require(stableCoin.allowance(buyer, address(this)) >= priceDiff, "E16"); price = listingOffer.sellerPrice; require(stableCoin.transferFrom(buyer, address(this), priceDiff),"E41"); } else if (msg.sender == listing.seller) { require(listingOffer.isCallable, "E38"); price = listingOffer.buyerPrice; if (listingOffer.sellerCount < 1) { listing.remainingQty -= quantity; } } else { revert("E36"); } if (listingOffer.sellerCount >= 1) { listing.tokenInHold -= quantity; } uint256 totalAmount = quantity * price; listingOffer.status = Status.Sold; if (listing.remainingQty < 1 && listing.tokenInHold < 1) { listing.status = Status.Sold; } uint256 finalAmount = totalAmount; if(whitelist.isUserUSA(msg.sender) == listing.isUsUSer && feeStatusUS ){ feeAmount = ((totalAmount * feePercentageUS) / 100 ether)*2; require(stableCoin.transfer(feeAddress, feeAmount),"E41"); finalAmount -= feeAmount; }else if(whitelist.isUserForeign(msg.sender) != listing.isUsUSer && feeStatusNonUS){ feeAmount = ((totalAmount * feePercentageNonUS) / 100 ether)*2; require(stableCoin.transfer(feeAddress, feeAmount),"E41"); finalAmount -= feeAmount; } if (marginLoanStatus) { uint256 payToSeller = adjustLoan( address(listing.token), listing.seller, finalAmount ); finalAmount = payToSeller; } if (finalAmount != 0) { require(stableCoin.transfer(listing.seller, finalAmount),"E41"); } require(listing.token.transfer(buyer, quantity),"E41"); listing.token.updateFromExchange(listing.seller, quantity); ///@dev null all offers made on this listing. nullOffer(id); emit TokensPurchased(id,listingOffer.quantity,price,listing.seller,buyer, listing.token, feeAddress, feeAmount *2 ); } /** * @dev buyer cancel the given offer * @param id: id of offers mapping */ function cancelBuyer( uint256 id ) public override onlyAdminAndBuyer(id) nonReentrant { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); Offers storage listingOffer = listingOffers[msg.sender][id]; require(msg.sender == listingOffer.buyer, "E40"); require( listingOffer.status != Status.Default && listingOffer.status != Status.Canceled, "E21" ); uint128 price = listingOffer.buyerPrice; uint128 quantity = listingOffer.quantity; uint256 totalAmount = (quantity * price) + listingOffer.buyerFeeAmount; if (listingOffer.sellerCount >= 1) { listing.tokenInHold -= quantity; listing.remainingQty += quantity; } listingOffer.status = Status.Canceled; require(stableCoin.transfer(msg.sender, totalAmount),"E41"); emit BuyerOfferCanceled(id,quantity, price, listing.token, listing.seller,msg.sender); } /** * @dev seller: cancel the given offer * @param id: id of offers mapping * @param buyer: buyer address */ function cancelSeller( uint256 id, address buyer ) public override onlyAdminAndSeller(id) { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); require(msg.sender == listing.seller, "E40"); Offers storage listingOffer = listingOffers[buyer][id]; require( listingOffer.status != Status.Default && listingOffer.status != Status.Canceled, "E21" ); uint128 price = listingOffer.buyerPrice; uint128 quantity = listingOffer.quantity; uint256 buyerOfferFee = listingOffer.buyerFeeAmount; uint256 totalAmount = (quantity * price) + buyerOfferFee; if (listingOffer.sellerCount >= 1) { listing.tokenInHold -= quantity; listing.remainingQty += quantity; } listingOffer.status = Status.Canceled; require(stableCoin.transfer(buyer, totalAmount),"E41"); emit SellerOfferCanceled( id, quantity, totalAmount, price, listing.token, msg.sender, buyer ); } /** * @dev pay back the loan of seller if any * @param token: address or security token * @param seller: seller of token (borrower) * @param totalAmount: total selling amount of tokens * @return remaining akusd amount to be payed to seller after loan payment */ function adjustLoan( address token, address seller, uint256 totalAmount ) private returns (uint256) { (address[] memory banks, uint256[] memory loanAmounts, , ) = marginLoan .getTotalLoanOfToken(seller, token); (uint256[] memory ids, uint256[] memory loans) = marginLoan .getTotalNoOfTokens(seller, token); uint256 len = banks.length; if (len > 0) { for (uint128 i = 0; i < len; ) { if (totalAmount == 0) { break; } if (loans[i] <= totalAmount) { uint256 remainingAmount = totalAmount - loanAmounts[i]; totalAmount = remainingAmount; require(stableCoin.transfer(banks[i], loanAmounts[i]),"E41"); marginLoan.updateLoan(seller, ids[i], 0, 1); emit LoanPayed( loanAmounts[i], IERC1400RawERC20(token), seller, banks[i] ); } else if (loans[i] > totalAmount) { uint256 remainingLoan = loanAmounts[i] - totalAmount; uint256 payableLoan = totalAmount; totalAmount = 0; bool isLoanTransfer = stableCoin.transfer(banks[i], payableLoan); require(isLoanTransfer,"E41"); marginLoan.updateLoan(seller, ids[i], remainingLoan, 2); emit LoanPayed( payableLoan, IERC1400RawERC20(token), seller, banks[i] ); } unchecked { ++i; } } } return totalAmount; } /** * @dev update WhiteListing address * @param newWhitelist: address or security token */ function updateWhiteListing( IAkruNFTWhitelist newWhitelist ) external override onlyAdmin { whitelist = newWhitelist; emit UpdateWhiteListing(msg.sender, address(whitelist)); } /** * @dev update StableCoin address * @param newStableCoin: address or security token */ function updateStableCoin( IStableCoin newStableCoin ) external override onlyAdmin { stableCoin = newStableCoin; emit UpdateStableCoin(msg.sender, address(newStableCoin)); } /** * @dev update MarginLoan * @param newMarginLoan: address or security token */ function updateMarginLoan( IMarginLoan newMarginLoan ) external override onlyAdmin { marginLoan = newMarginLoan; emit UpdateMarginLoan(msg.sender, address(newMarginLoan)); } /** * @dev setFeeAddress * @param newFeeAddress: set fee address */ function setFeeAddress(address newFeeAddress) external override onlyAdmin { require(newFeeAddress != address(0), "E32"); feeAddress = newFeeAddress; emit SetFeeAddress(msg.sender, newFeeAddress); } /** * @dev set Fee Percentage for US user * @param newFeePercentage: set fee percentage */ function setFeePercentageUS( uint128 newFeePercentage // in wei ) external override onlyAdmin { feePercentageUS = newFeePercentage; emit SetFeePercentage(msg.sender, newFeePercentage, "US"); } /** * @dev set Fee Percentage for US user * @param newFeePercentage: set fee percentage */ function setFeePercentageNonUS( uint128 newFeePercentage // in wei ) external override onlyAdmin { feePercentageNonUS = newFeePercentage; emit SetFeePercentage(msg.sender, newFeePercentage, "Non-US"); } /** * @dev toggleMarginLoan */ function toggleMarginLoan() external override onlyAdmin { marginLoanStatus = !marginLoanStatus; emit ToggleMarginLoan(msg.sender, marginLoanStatus); } /** * @dev Toggle Fee US side */ function toggleFeeUS() external override onlyAdmin { feeStatusUS = !feeStatusUS; emit ToggleFee(msg.sender, feeStatusUS, "US"); } /** * @dev Toggle Fee on Non US */ function toggleFeeNonUS() external override onlyAdmin { feeStatusNonUS = !feeStatusNonUS; emit ToggleFee(msg.sender, feeStatusNonUS, "Non-US"); } /** * @dev set expiry duration */ function setExpiryDuration(uint256 newExpiryDuration) external override onlyAdmin { expiryDuration = newExpiryDuration; emit SetExpiryDuration(msg.sender,newExpiryDuration); } /** * @dev Mark offer as expired and transfer akued amount to buyer * @notice This function is called from backend in api/exchange/active/ API */ function expireOffer(uint256 id, address buyer) external override onlyAdmin { ListTokens storage listing = listedTokens[id]; require(listing.status == Status.Listed, "E11"); Offers storage listingOffer = listingOffers[buyer][id]; require( listingOffer.status == Status.Created || listingOffer.status == Status.Countered, "E21" ); require(block.timestamp > listingOffer.expiryTime,"E39"); uint128 price = listingOffer.buyerPrice; uint128 quantity = listingOffer.quantity; uint256 totalAmount = (quantity * price) + listingOffer.buyerFeeAmount; if (listingOffer.sellerCount >= 1) { listing.tokenInHold -= quantity; listing.remainingQty += quantity; } listingOffer.status = Status.Expired; require(stableCoin.transfer(buyer, totalAmount),"E41"); emit OfferExpire(id,buyer,totalAmount); } /** * @dev single token status update * @param token address of token * @param status status of token */ function tokenStatus(address token, bool status)public onlyAdmin{ isTokenAccepted[token] = status; emit TokenStatus(msg.sender, token,address(0), status); } /** * @dev Add 2 tokens or remove 2 tokens at a time on exchange * @param token1 token1 address that want to give permision on exchnage * @param token2 token2 address that want to give permision on exchnage * @param status Status of Tokens it will be true for active false for deactivate */ function tokenStatus(address token1, address token2, bool status) public onlyAdmin{ isTokenAccepted[token1] = status; isTokenAccepted[token2] = status; emit TokenStatus(msg.sender, token1, token2, status); } /** * @dev Its changing status is US and NON US user purchase and sell in between them * @param status status of Exchange Excepting for both */ function isExchangeForBoth(bool status)public onlyAdmin{ isOpenForBoth = status; emit IsExchangeForBoth(status, msg.sender); } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"contract IStableCoin","name":"stableCoinAddress","type":"address"},{"internalType":"contract IAkruNFTWhitelist","name":"whitelistingAddress","type":"address"},{"internalType":"contract IMarginLoan","name":"marginLoanAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"}],"name":"BuyerOfferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"buyerFee","type":"uint256"}],"name":"Counter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"IsExchangeForBoth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"}],"name":"ListingCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"bankAddress","type":"address"}],"name":"LoanPayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"OfferExpire","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"}],"name":"RejectCounter","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"}],"name":"SellerOfferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"expiryDuration","type":"uint256"}],"name":"SetExpiryDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"newFeeAddress","type":"address"}],"name":"SetFeeAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint128","name":"newFeePercentage","type":"uint128"},{"indexed":false,"internalType":"string","name":"area","type":"string"}],"name":"SetFeePercentage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"feeStatus","type":"bool"},{"indexed":false,"internalType":"string","name":"area","type":"string"}],"name":"ToggleFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"marginLoanStatus","type":"bool"}],"name":"ToggleMarginLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"token2","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"TokenStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"}],"name":"TokensListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"price","type":"uint128"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"feeAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"TokensPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"newMarginLoan","type":"address"}],"name":"UpdateMarginLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"newStableCoin","type":"address"}],"name":"UpdateStableCoin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"whitelist","type":"address"}],"name":"UpdateWhiteListing","type":"event"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"}],"name":"acceptCounter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"quantity","type":"uint128"}],"name":"buyTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"uint128","name":"price","type":"uint128"}],"name":"buyerOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelBuyer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"}],"name":"cancelSeller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"counterAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"address","name":"seller","type":"address"}],"name":"counterBuyer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"address","name":"buyer","type":"address"}],"name":"counterSeller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"}],"name":"expireOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expiryDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercentageNonUS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercentageUS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeStatusNonUS","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeStatusUS","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getListings","outputs":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"uint128","name":"remainingQty","type":"uint128"},{"internalType":"uint128","name":"tokenInHold","type":"uint128"},{"internalType":"contract IERC1400RawERC20","name":"token","type":"address"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"enum IUniversalExchange.Status","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"buyerWallet","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getOffer","outputs":[{"internalType":"uint128","name":"buyerPrice","type":"uint128"},{"internalType":"uint128","name":"sellerPrice","type":"uint128"},{"internalType":"uint256","name":"expiryTime","type":"uint256"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint8","name":"buyerCount","type":"uint8"},{"internalType":"uint8","name":"sellerCount","type":"uint8"},{"internalType":"bool","name":"isOffered","type":"bool"},{"internalType":"bool","name":"isCallable","type":"bool"},{"internalType":"enum IUniversalExchange.Status","name":"status","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"isExchangeForBoth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOpenForBoth","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isOrderExist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isTokenAccepted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marginLoan","outputs":[{"internalType":"contract IMarginLoan","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marginLoanStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"}],"name":"rejectCounter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"contract IERC1400RawERC20","name":"token","type":"address"}],"name":"sellTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newExpiryDuration","type":"uint256"}],"name":"setExpiryDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeAddress","type":"address"}],"name":"setFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newFeePercentage","type":"uint128"}],"name":"setFeePercentageNonUS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newFeePercentage","type":"uint128"}],"name":"setFeePercentageUS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stableCoin","outputs":[{"internalType":"contract IStableCoin","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleFeeNonUS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleFeeUS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleMarginLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"tokenStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"token2","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"tokenStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IMarginLoan","name":"newMarginLoan","type":"address"}],"name":"updateMarginLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IStableCoin","name":"newStableCoin","type":"address"}],"name":"updateStableCoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAkruNFTWhitelist","name":"newWhitelist","type":"address"}],"name":"updateWhiteListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"contract IAkruNFTWhitelist","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608034620000c357601f620050f138819003918201601f19168301916001600160401b03831184841017620000c857808492606094604052833981010312620000c35780516001600160a01b039182821691829003620000c357602081015190838216809203620000c35760400151928316809303620000c357600160005562ffffff196008541660085561025860095560018060a01b03199182600254161760025581600354161760035560045416176004556040516150129081620000df8239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c9081624633e814613c81575080630560bd9614613c425780630a35c1b114613bdb578063134f923a14613baa5780631550284014613b595780631d907aad14613b3b5780631df7f75d14613adb57806325f7d0da1461359e57806329918de8146135755780632d6fc8b814613503578063305a67a81461332357806341275358146132fa57806341654afe146132d75780634cb9f6be14612a1b57806353658474146127585780635cbf736c146125315780636b855499146125135780636b98a783146124785780636fcc6fe214612406578063748581141461237e578063800e9fc8146120465780638705fcd414611fa55780638836d1b6146117485780638c314aa2146116da57806393e59dc1146116b1578063992642e51461168857806399497392146116095780639ece06b9146110f4578063ac71045e14611028578063afbe93ea14610f6a578063afe3acbe14610d4f578063b3ee142414610d31578063b6804d2614610619578063d33fc15b146105f6578063d4667e1f146103b9578063deff0a8714610338578063e0baeb29146102c6578063e94fbddc14610253578063ea09addb146102015763feb6fc54146101d657600080fd5b346101fc5760003660031901126101fc57602060ff60085460101c166040519015158152f35b600080fd5b346101fc5760403660031901126101fc57602435600435600052600c602052604060002080548210156101fc5760209161023a91613d43565b905460405160039290921b1c6001600160a01b03168152f35b346101fc5760203660031901126101fc577fdfb566df311ab7d36db560baa2dfa712a0f8607e2191334e8ca9980c82d8bf7f61028d613ce6565b610295614f03565b60018060801b03168060065560405190338252602082015260606040820152806102c160608201614f8e565b0390a1005b346101fc5760203660031901126101fc576004356001600160a01b038116908190036101fc576102c17f6d0d4f3bbf1677103286e779f4f135f87a46fd578e098f2e2bf9925d24443a7991610319614f03565b600280546001600160a01b031916821790556040519182913383613ddd565b346101fc5760003660031901126101fc57610351614f03565b7fd90631fdf6573dd5c9c58aa69cc22c34d15174f68cf479adda0b261539171b6760085462ff000060ff8260101c161560101b169062ff00001916178060085560ff6040519133835260101c161515602082015260606040820152806102c160608201614fa3565b346101fc576020806003193601126101fc57600435906103d8826143ee565b6103e0613e93565b81600052600a8152604060002090600382019060ff825460a01c16600a8110156105e05760016104109114613fe9565b33600052600b815260406000208460005281526040600020906004820193845460018060a01b0361044481831633146141d4565b60ff8260c01c16600a8110156105e0578061046891151590816105d4575b5061438a565b845460028601546001600160801b03908116969181169386928261048c878b614098565b916003015491169061049d916140c7565b9060a81c60ff1660011115996104ec9260009b610592575b50805460ff60c01b1916600360c11b17905560025460405163a9059cbb60e01b81529a8b9391861692849283913360048401614141565b03925af1968715610586578160a0976105317f46571b86db3f0be7e4bb394a36e55b373c8177acc15e1909a6f8a3b1d41dfe9c9a600294600091610559575b50613e61565b5416930154169260405194855284015260408301526060820152336080820152a26001600055005b6105799150893d8b1161057f575b6105718183613dbc565b810190613df7565b8d61052b565b503d610567565b6040513d6000823e3d90fd5b60018801906105ae6105a88c845460801c6140d4565b83613e1b565b8154906105bd8c828416614238565b6001600160801b031990921691161790558c6104b5565b6006915014158a610462565b634e487b7160e01b600052602160045260246000fd5b346101fc5760003660031901126101fc57602060ff600854166040519015158152f35b346101fc5760603660031901126101fc57610632613cd0565b6044356001600160801b03811690036101fc5761064d613ee9565b6001600160801b03811615610d0757600435600052600a602052604060002060038101549160ff8360a01c16600a8110156105e057600161068e9114613fe9565b60028201546001600160a01b03163314610cdc5781546001600160801b039081169060443516811115610cb15733600052600b602052604060002060043560005260205260ff60046040600020015460b01c16610c86576001830154610703906001600160801b03908116908416111561401b565b60ff600e541615610c10575b6001600160801b0361072360443584614098565b169360009060018060a01b0360035416604051637e9ad37f60e01b8152336004820152602081602481855afa90811561058657600091610bf1575b5060ff8360a81c1615159015151480610be2575b15610b415750505061079b68056bc75e2d63100000610793600654876140b4565b0480956140c7565b905b6002546040516370a0823160e01b81523360048201526001600160a01b0390911690602081602481855afa8015610586578491600091610b0c575b50101580610a97575b6107eb91506140ed565b6107f7600954426140c7565b6040519161080483613d8d565b60018060801b036044351683526020830152604082015260018060801b03831660608201528460808201523360a0820152600160c0820152600060e082015260016101008201526001610120820152600461014082015233600052600b602052604060002060043560005260205260406000209060018060801b0381511660018060801b031990818454161783556108a860018060801b0360208401511684613e1b565b604082015160018401556060820151600284018054929092166001600160801b039091161790556080810151600383015560a08082015160048401805460c085015160e0860151941b60ff60a01b166001600160a01b039093166001600160b01b0319909116179190911760a89290921b60ff60a81b16919091179081905561010082015161012083015161014090930151929015159160ff60b81b91151560b81b9190911690600a8410156105e05762ffffff60b01b191660b09290921b60ff60b01b16919091171760c09190911b60ff60c01b1617600491820155356000908152600c602052604090208054600160401b811015610a81576000926109ba8260209460016109fd95018155613d43565b81549060031b9033821b9160018060a01b03901b191617905560018060a01b0360025416906040519485809481936323b872dd60e01b835230336004850161411f565b03925af1801561058657610a1891600091610a625750613e61565b600282015460039092015460405133946001600160a01b039485169460043594600080516020614fbd833981519152948493610a5d93909291169060443590856141a2565b0390a4005b610a7b915060203d60201161057f576105718183613dbc565b8561052b565b634e487b7160e01b600052604160045260246000fd5b5060206040518092636eb1769f60e11b82528180610ab9303360048401613ddd565b03915afa801561058657600090610ad8575b6107eb91508311156107e1565b506020813d602011610b04575b81610af260209383613dbc565b810103126101fc576107eb9051610acb565b3d9150610ae5565b9150506020813d602011610b39575b81610b2860209383613dbc565b810103126101fc57839051886107d8565b3d9150610b1b565b906020602492604098959498519384809263179c54c560e31b82523360048301525afa91821561058657600092610bbe575b5060ff9060a81c161515901515141580610baf575b1561079d57909350610ba968056bc75e2d63100000610793600754876140b4565b9061079d565b5060ff60085460101c16610b88565b60ff919250610bdb9060203d60201161057f576105718183613dbc565b9190610b73565b5060ff60085460081c16610772565b610c0a915060203d60201161057f576105718183613dbc565b8861075e565b60035460405163179c54c560e31b815233600482015290602090829060249082906001600160a01b03165afa801561058657610c6291600091610c67575b5060ff8660a81c161515901515141561404d565b61070f565b610c80915060203d60201161057f576105718183613dbc565b86610c4e565b60405162461bcd60e51b815260206004820152600360248201526245313960e81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600360248201526208a62760eb1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600360248201526245313760e81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600260248201526108a760f31b6044820152606490fd5b346101fc5760003660031901126101fc576020600954604051908152f35b346101fc5760403660031901126101fc57600435610d6b613cba565b90610d74614f03565b80600052602090600a8252604060002060ff600382015460a01c16600a8110156105e0576001610da49114613fe9565b60018060a01b03938481169485600052600b85526040600020846000528552604060002092600484019081549460ff8660c01c16600a8110156105e057806004610df69214908115610f5f575061438a565b6001810154421115610f34579260ff9592610e84999592899560018060801b03916001610e3f8484541693856003610e35826002850154169788614098565b92015491166140c7565b9a8b9860a81c161015610ef2575b505050600960c01b60ff60c01b1982541617905560025416906000604051809a8195829463a9059cbb60e01b845260048401614141565b03925af193841561058657610ec46060957f6a75dab2bd978161ef5cbb30eef294670b4173fc5d5e431d4154984ee1c038ec97600091610ed55750613e61565b6040519384528301526040820152a1005b610eec9150833d851161057f576105718183613dbc565b8861052b565b60010191610f0d610f0783855460801c6140d4565b84613e1b565b610f1b835492828416614238565b6001600160801b031990921691161790558a8080610e4d565b60405162461bcd60e51b815260048101899052600360248201526245333960e81b6044820152606490fd5b60059150148b610462565b346101fc5760603660031901126101fc57610f83613ca4565b610f8b613cba565b90604435918215158084036101fc577fe3b90c1050effb1c6805ce6b5abdb0320db3b920b8699ddbe756686850b5e1d39361100f608094610fca614f03565b6001600160a01b039081166000818152600d60205260409020805460ff191660ff861515161790559416918260005260406000209060ff801983541691151516179055565b60405192338452602084015260408301526060820152a1005b346101fc5760403660031901126101fc576101406001600160a01b038061104d613ca4565b16600052600b60205260406000206024356000526020526110f260406000209182549060018401549360018060801b039460048660028401541692015493604051968116875260801c6020870152604086015260608501528116608084015260ff8160a01c1660a084015260ff8160a81c1660c084015260ff8160b01c16151560e084015260ff8160b81c16151561010084015260ff61012084019160c01c16613d36565bf35b346101fc5760803660031901126101fc5761110d613ce6565b611115613cd0565b606435916001600160a01b03831683036101fc57611131613e93565b611139613ee9565b6001600160a01b0383166000908152600d602052604090205460ff16156115de57604435600052600160205260ff604060002054166115b3576001600160801b0381161515806115a1575b15611577576040516370a0823160e01b81523360048201526020816024816001600160a01b0388165afa90811561058657600091611545575b506001600160801b0383161161151b57604051636eb1769f60e11b8152602081806111ec303360048401613ddd565b03816001600160a01b0388165afa908115610586576000916114e9575b506001600160801b038316116114be5760035460405163179c54c560e31b815233600482015290602090829060249082906001600160a01b03165afa9081156105865760009161149f575b50156114985760005b6040519061126a82613d71565b6001600160801b03838116835284811660208085018281526040808701939093526000606087018190523360808801526001600160a01b038a1660a0880152600160c0880190815295151560e088019081526044358252600a90935292909220855181549085166001600160801b031991821617825592519193600393919261132192916112f9911684613e1b565b60408701516001840180549092166001600160801b0391821617825560608801511690613e1b565b60808501516002820180546001600160a01b0319166001600160a01b0392831617905560a0959095015191018054935190949092911690600a8310156105e0575160a09290921b60ff60a01b166001600160b01b0319909316179190911790151560a81b60ff60a81b1617905560405163ed13a51b60e01b8152602081806113ad863360048401613e3e565b038160006001600160a01b0389165af1801561058657611479575b506040516323b872dd60e01b81523360048201523060248201526001600160801b038316604482015260208160648160006001600160a01b0389165af180156105865761141c91600091610a625750613e61565b604080516001600160801b0392831681529190921660208201526001600160a01b03909216913391604435917f86d958ab6de9570add5b66db79e4b426a8c20c0bb9e8658d427cff86e58190e591819081015b0390a46001600055005b6114919060203d60201161057f576105718183613dbc565b50836113c8565b600161125d565b6114b8915060203d60201161057f576105718183613dbc565b84611254565b60405162461bcd60e51b815260206004820152600360248201526204531360ec1b6044820152606490fd5b90506020813d602011611513575b8161150460209383613dbc565b810103126101fc575184611209565b3d91506114f7565b60405162461bcd60e51b8152602060048201526002602482015261453960f01b6044820152606490fd5b90506020813d60201161156f575b8161156060209383613dbc565b810103126101fc5751846111bd565b3d9150611553565b60405162461bcd60e51b8152602060048201526002602482015261453760f01b6044820152606490fd5b506001600160801b0382161515611184565b60405162461bcd60e51b815260206004820152600360248201526245343360e81b6044820152606490fd5b60405162461bcd60e51b8152602060048201526003602482015262229a1960e91b6044820152606490fd5b346101fc5760003660031901126101fc57611622614f03565b7fd90631fdf6573dd5c9c58aa69cc22c34d15174f68cf479adda0b261539171b6760085461ff0060ff8260081c161560081b169061ff001916178060085560ff6040519133835260081c161515602082015260606040820152806102c160608201614f8e565b346101fc5760003660031901126101fc576002546040516001600160a01b039091168152602090f35b346101fc5760003660031901126101fc576003546040516001600160a01b039091168152602090f35b346101fc5760203660031901126101fc577fdfb566df311ab7d36db560baa2dfa712a0f8607e2191334e8ca9980c82d8bf7f611714613ce6565b61171c614f03565b60018060801b03168060075560405190338252602082015260606040820152806102c160608201614fa3565b346101fc5760403660031901126101fc57611761613cd0565b611769613ee9565b611771613e93565b600435600052600a60205260406000209060038201549060ff8260a01c16600a8110156105e05760016117a49114613fe9565b60028301546001600160a01b03163314611f7a576001600160801b0381168015611f4f576001840154906117e3906001600160801b038316101561401b565b60ff600e541615611ed9575b83546001600160801b0390811694906118088685614098565b16600060018060a01b0360035416604051637e9ad37f60e01b8152336004820152602081602481855afa90811561058657600091611eba575b5060ff8860a81c1615159015151480611eab575b15611e1057505061187d68056bc75e2d63100000611875600654846140b4565b0480926140c7565b925b6001600160801b03611893868383166140d4565b166001600160801b03199190911681176001840181905590159081611e04575b50611dec575b600354604051637e9ad37f60e01b8152336004820152906001600160a01b0316602082602481845afa91821561058657600092611dcb575b5060ff600385015460a81c161515809215151480611dbc575b15611d2e57505050611933683635c9adc5dea0000061192b600654856140b4565b0480936140c7565b6002546040516370a0823160e01b81523360048201526001600160a01b0390911690602081602481855afa8015610586578391600091611cf9575b50101580611c85575b611980906140ed565b602060405180926323b872dd60e01b8252816000816119a48830336004850161411f565b03925af18015610586576119bf91600091611c6c5750613e61565b60085460ff8160081c16908115611c5e575b50611bbe575b60ff60085416611b98575b80611b39575b5060405163a9059cbb60e01b815260208180611a08873360048401613e3e565b6001600160a01b039098169703816000895af1801561058657611a3291600091611b1a5750613e61565b600281015460405163189433bf60e31b81529060209082908190611a649088906001600160a01b031660048401613e3e565b03816000895af1801561058657611afb575b50611a826004356144b3565b6002908101546005546001600160a01b0391821695600185901b9491909216928115918504141715611ae55761146f7f6999ec10c5fd4d6b5e6667e2d6994da6d3b01b860d93cc075d92f3d511d840a39360405193849333996004359886614169565b634e487b7160e01b600052601160045260246000fd5b611b139060203d60201161057f576105718183613dbc565b5085611a76565b611b33915060203d60201161057f576105718183613dbc565b8761052b565b600280549083015460405163a9059cbb60e01b81529260209284926001600160a01b039182169284926000928492611b779290911660048401614141565b03925af1801561058657611b9291600091611b1a5750613e61565b856119e8565b60038201546002830154611bb992916001600160a01b039182169116614983565b6119e2565b600280546005546001600160a01b039081169392911690600186901b8690041485151715611ae557611c1060209160009460405195868094819363a9059cbb60e01b83528b60011b9060048401614141565b03925af191821561058657611c3a92611c3091600091611c3f5750613e61565b8360011b9061415c565b6119d7565b611c58915060203d60201161057f576105718183613dbc565b8961052b565b60ff915060101c16876119d1565b610eec915060203d60201161057f576105718183613dbc565b50604051636eb1769f60e11b815260208180611ca5303360048401613ddd565b0381855afa8015610586578390600090611cc3575b10159050611977565b50506020813d602011611cf1575b81611cde60209383613dbc565b810103126101fc57826119809151611cba565b3d9150611cd1565b9150506020813d602011611d26575b81611d1560209383613dbc565b810103126101fc578290518961196e565b3d9150611d08565b60206024916040969496519283809263179c54c560e31b82523360048301525afa90811561058657600091611d9d575b501515141580611d8e575b15611933579150611d8968056bc75e2d6310000061192b600754856140b4565b611933565b5060ff60085460101c16611d69565b611db6915060203d60201161057f576105718183613dbc565b88611d5e565b5060ff60085460081c1661190a565b611de591925060203d60201161057f576105718183613dbc565b90886118f1565b60ff60a01b198516600360a01b1760038301556118b9565b905060801c15876118b3565b6020602491604096939496519283809263179c54c560e31b82523360048301525afa90811561058657600091611e8c575b5060ff8760a81c161515901515141580611e7d575b1561187f57929050611e7768056bc75e2d63100000611875600754846140b4565b9261187f565b5060ff60085460101c16611e56565b611ea5915060203d60201161057f576105718183613dbc565b88611e41565b5060ff60085460081c16611855565b611ed3915060203d60201161057f576105718183613dbc565b89611841565b60035460405163179c54c560e31b815233600482015290602090829060249082906001600160a01b03165afa801561058657611f2b91600091611f30575b5060ff8560a81c161515901515141561404d565b6117ef565b611f49915060203d60201161057f576105718183613dbc565b86611f17565b60405162461bcd60e51b815260206004820152600360248201526245313360e81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600360248201526222989960e91b6044820152606490fd5b346101fc5760203660031901126101fc57611fbe613ca4565b611fc6614f03565b6001600160a01b038116801561201b57600580546001600160a01b03191690911790556040517fd44190acf9d04bdb5d3a1aafff7e6dee8b40b93dfb8c5d3f0eea4b9f4539c3f79181906102c1903383613ddd565b60405162461bcd60e51b815260206004820152600360248201526222999960e91b6044820152606490fd5b346101fc5761205436613cfc565b9161205e81614262565b80600052602092600a845260406000209360018060a01b038092169485600052600b82526040600020846000528252604060002092600382019560ff875460a01c16600a8110156105e0576001148061234c575b1561231d57600485019485549160ff8360b81c16156122f25760028501966120de8589541633146141d4565b60018301916120ef83544210614206565b83546001600160801b0382811698909690918781168a1190816122e5575b816122d8575b50156122ad5760a81c60ff166002811015612282576001116121d1575b5085936080989693600080516020614fbd8339815191529a989693612168600294600560c01b60ff60c01b1984541617835584613e1b565b61219561217b60ff835460a81c16614251565b825460ff60a81b191660a89190911b60ff60a81b16178255565b805460ff60b81b191690556009546121ad90426140c7565b905501541694541697541691604051938452830152604082015260006060820152a4005b6002850160018782541692019182549088821680821161225757946122458b9995600080516020614fbd8339815191529f9d9b989460809f9d9a968a61223f92816122216121689960029e6140d4565b6001600160801b03199092169116178085559154169060801c614238565b90613e1b565b9450509396989a509350939597612130565b60405162461bcd60e51b8152600481018e9052600360248201526245323760e81b6044820152606490fd5b60405162461bcd60e51b8152600481018b9052600360248201526222991b60e91b6044820152606490fd5b60405162461bcd60e51b8152600481018b9052600360248201526245323360e81b6044820152606490fd5b905060801c89108f612113565b835489168b10915061210d565b60405162461bcd60e51b815260048101879052600360248201526204532360ec1b6044820152606490fd5b60405162461bcd60e51b81526004810185905260076024820152664531312f45323160c81b6044820152606490fd5b5060ff600486015460c01c16600a8110156105e05760048114908115612373575b506120b2565b60059150148961236d565b346101fc5760203660031901126101fc57600435600052600a60205260e060406000206110f28154916001810154600260038301549260018060a01b03918291015416916040519560018060801b0390818116885260801c60208801528116604087015260801c60608601528216608085015260a084015260ff60c084019160a01c16613d36565b346101fc5760203660031901126101fc576004356001600160a01b038116908190036101fc576102c17f55f08db7384bf90313e8fde11a2e7f56428c41de71d623e4a0a7e44da292d4b491612459614f03565b600380546001600160a01b031916821790556040519182913383613ddd565b346101fc5760403660031901126101fc57612491613ca4565b60243590811515918281036101fc577fe3b90c1050effb1c6805ce6b5abdb0320db3b920b8699ddbe756686850b5e1d3926124f86080936124d0614f03565b60018060a01b03169283600052600d60205260406000209060ff801983541691151516179055565b604051913383526020830152600060408301526060820152a1005b346101fc5760003660031901126101fc576020600754604051908152f35b346101fc5760403660031901126101fc5760043561254d613cba565b61255682614262565b81600052600a602052604060002060ff600382015460a01c16600a8110156105e05760016125849114613fe9565b61259b60018060a01b0360028301541633146141d4565b60018060a01b038216600052600b602052604060002083600052602052604060002060048101549260ff8460c01c16600a8110156105e057806125e6911515908161274c575061438a565b8154600283015460038401546001600160801b039283169691831694919260019160ff9161261f91906126198b8a614098565b166140c7565b9360a81c161015612705575b6004600360c11b60ff60c01b1982840154161791015560018060a01b0360025416946020604051809763a9059cbb60e01b825281600081612670888a60048401614141565b03925af1948515610586576126b060c0967f3cffeadcef57ee86f573b3a39ff11361908e0b470749e59428e1ddcdba13004d986000916126e65750613e61565b60030154604080519586526020860193909352918401526001600160a01b0390811660608401523360808401521660a0820152a2005b6126ff915060203d60201161057f576105718183613dbc565b8a61052b565b6001850161272061271a86835460801c6140d4565b82613e1b565b80546001600160801b0361273687828416614238565b6001600160801b0319909216911617905561262b565b60069150141587610462565b346101fc5760403660031901126101fc57600435612774613cba565b9061277e8161471a565b80600052600a60205260406000209060018060a01b0383169283600052600b602052604060002082600052602052604060002092600381019360ff855460a01c16600a8110156105e05760016127d49114613fe9565b60048101549260ff8460c01c16600a8110156105e0578060046127ff9214908115612a10575061438a565b6002830154336001600160a01b039091160361299d5760ff8460b81c16156129725760206128b5945b835460028501546001600160801b039081169591169390600160ff612862612850888a614098565b600385015490848060801b03166140c7565b9460a81c161015612921575b6004908101805460ff60c01b1916600760c01b17905560025460405163a9059cbb60e01b81529889946001600160a01b039290921693859360009385939290918401614141565b03925af1928315610586576128f56060947f882e27099dd26b54f1efe3a5bc506db364198b6be6e9e3099f1a58dc32232c43966000916126e65750613e61565b600260018060a01b03910154169560018060a01b039054169060405192835260208301526040820152a4005b60018701805461296d919061223f906001600160801b036129448b828416614238565b6001600160801b031990921691161780835560028501546001600160801b03169060801c6140d4565b61286e565b60405162461bcd60e51b815260206004820152600360248201526245333560e81b6044820152606490fd5b3387036129e55760ff8460b81c166129ba5760206128b594612828565b60405162461bcd60e51b8152602060048201526003602482015262114ccd60ea1b6044820152606490fd5b60405162461bcd60e51b815260206004820152600360248201526222999b60e91b6044820152606490fd5b600591501489610462565b346101fc5760403660031901126101fc57612a34613cba565b612a3f60043561471a565b612a47613e93565b600435600052600a602052604060002060ff600382015460a01c16600a8110156105e0576001612a779114613fe9565b60018060a01b038216600052600b6020526040600020600435600052602052604060002091600483015460ff8160c01c16600a8110156105e057806004612ac692149081156132cc575061438a565b60028401546001600160801b031691600091336001600160a01b03831603613231575060ff600486015460b81c1661320657845494612b1d846001600160801b03612b17818a1660808b901c6140d4565b166140b4565b600354604051637e9ad37f60e01b8152336004820152919491906001600160a01b0316602082602481845afa918215610586576000926131e5575b5060ff600389015460a81c1615158092151514806131d6575b1561314557505050612b9a68056bc75e2d63100000612b92600654866140b4565b0480946140c7565b955b600254604051636eb1769f60e11b81526001600160a01b03909116919060208180612bcb308960048401613ddd565b0381865afa801561058657899160009161310f575b5092602092612bf6612c189360009610156143bc565b60801c996040519485809481936323b872dd60e01b8352308b6004850161411f565b03925af1801561058657612c3391600091611c6c5750613e61565b600160ff600483015460a81c1610156130f5575b6001600160801b03612c598786614098565b600483018054600360c01b60ff60c01b1990911617905560018781015491909216916001600160801b0382161090816130e7575b506130cd575b600354604051637e9ad37f60e01b81523360048201529194859290916001600160a01b0316602082602481845afa918215610586576000926130ac575b5060ff60038a015460a81c16151580921515148061309d575b15612f9057505050612d0868056bc75e2d6310000091600654906140b4565b0492838060011b0460021484151715611ae55760025460055460405163a9059cbb60e01b8152600187901b96909392909160209185916001600160a01b039182169183916000918391612d61918e911660048401614141565b03925af192831561058657612d8a93612d8191600091612f715750613e61565b60011b9061415c565b60ff60085416612f4b575b80612eec575b50600385015460405163a9059cbb60e01b81529060209082906001600160a01b031681600081612dcf8b8a60048401613e3e565b03925af1801561058657612dea91600091611c6c5750613e61565b600385015460028601805460405163189433bf60e31b81529196919260209284926001600160a01b039283169284926000928492612e2d92911660048401613e3e565b03925af1801561058657612ecd575b50612e486004356144b3565b60029081015493546003909501546005546001600160a01b03968716966001600160801b039690961695600186901b95928116949391169180159086049091141715611ae5577f6999ec10c5fd4d6b5e6667e2d6994da6d3b01b860d93cc075d92f3d511d840a39361146f9160405194859460018060a01b0316996004359886614169565b612ee59060203d60201161057f576105718183613dbc565b5086612e3c565b600280549087015460405163a9059cbb60e01b81529260209284926001600160a01b039182169284926000928492612f2a9290911660048401614141565b03925af1801561058657612f4591600091611c6c5750613e61565b86612d9b565b60038601546002870154612f6c92916001600160a01b039182169116614983565b612d95565b612f8a915060203d60201161057f576105718183613dbc565b8b61052b565b6020602491604098959498519283809263179c54c560e31b82523360048301525afa9081156105865760009161307e575b50151514158061306f575b612fd7575b50612d8a565b93505068056bc75e2d63100000612ff0600754856140b4565b0492838060011b0460021484151715611ae55760025460055460405163a9059cbb60e01b8152600187901b96909392909160209185916001600160a01b039182169183916000918391613049918e911660048401614141565b03925af19283156105865761306993612d8191600091612f715750613e61565b87612fd1565b5060ff60085460101c16612fcc565b613097915060203d60201161057f576105718183613dbc565b8a612fc1565b5060ff60085460081c16612ce9565b6130c691925060203d60201161057f576105718183613dbc565b908a612cd0565b60038601805460ff60a01b1916600360a01b179055612c93565b6001915060801c1088612c8d565b61310a6001860161223f86825460801c6140d4565b612c47565b9150506020813d60201161313d575b8161312b60209383613dbc565b810103126101fc575188906020612be0565b3d915061311e565b602060249160409a94979a519283809263179c54c560e31b82523360048301525afa908115610586576000916131b7575b5015151415806131a8575b15612b9c579592506131a268056bc75e2d63100000612b92600754866140b4565b95612b9c565b5060ff60085460101c16613181565b6131d0915060203d60201161057f576105718183613dbc565b89613176565b5060ff60085460081c16612b71565b6131ff91925060203d60201161057f576105718183613dbc565b9089612b58565b60405162461bcd60e51b815260206004820152600360248201526245333760e81b6044820152606490fd5b9460018060a01b0360028601541633146000146129e55760ff8660b81c16156132a15780546001600160801b031695600160a89190911c60ff161015612c33576001850180546001600160801b0361328b878284166140d4565b6001600160801b03199092169116179055612c33565b60405162461bcd60e51b815260206004820152600360248201526208a66760eb1b6044820152606490fd5b600591501486610462565b346101fc5760003660031901126101fc57602060ff600e54166040519015158152f35b346101fc5760003660031901126101fc576005546040516001600160a01b039091168152602090f35b346101fc576020806003193601126101fc576004359061334282614262565b61334a613e93565b81600052600a8152604060002091600383019182549360ff8560a01c16600a8110156105e057600161337c9114613fe9565b6002810180546001600160a01b03908116969192909161339d3389146141d4565b60ff60a01b198116600160a11b17875560018201805490986001600160801b03926133f792889291906133d790608081901c908716614238565b9160008860405180978196829563189433bf60e31b845260048401613e3e565b0393165af18015610586576134e6575b50613445858489541685875416906134268c54868160801c9116614238565b91600060405180968195829463a9059cbb60e01b845260048401613e3e565b03925af192831561058657613488859484937faac7581bfb0f0c1192c56ddab74deb78513a3b5a835679079216397e3b12addf996000926134c9575b5050613e61565b60008a55613495886144b3565b54169754169254169454169461146f6040519283928390602090939293604083019460018060801b03809216845216910152565b6134df9250803d1061057f576105718183613dbc565b8c80613481565b6134fc90863d881161057f576105718183613dbc565b5088613407565b346101fc5760203660031901126101fc576004356001600160a01b038116908190036101fc576102c17fa0ad39340f587c6e38efdc19533d6e16084e503f523c6842521d157c3e18a79191613556614f03565b600480546001600160a01b031916821790556040519182913383613ddd565b346101fc5760003660031901126101fc576004546040516001600160a01b039091168152602090f35b346101fc576135ac36613cfc565b90916135b7816143ee565b80600052600a6020526040600020926003604051946135d586613d71565b80546001600160801b038082168852608091821c602089015260018301549081166040890152811c606088015260028201546001600160a01b039081169188019190915291015490811660a080870191825290949160c087019160ff91906136429082901c831684613e0f565b60a81c16151560e087015251600a8110156105e05760016136639114613fe9565b60018060a01b0316600052600b60205260406000208260005260205260406000209060048201549060ff8260b81c16613ab05760ff8260c01c16600a8110156105e0578060046136bb9214908115613aa5575061438a565b6136ca60018401544210614206565b85516001600160801b039081169082161080613a8f575b80613a78575b15613a4d57600260ff8360a01c161015613a225782549261372a6001600160801b03613715818716856140d4565b60028401546001600160801b031691166140b4565b600354604051637e9ad37f60e01b81523360048201529194916000916001600160a01b031690602081602481855afa90811561058657600091613a03575b5060e08b0151151590151514806139f4575b1561395b57505061379a68056bc75e2d63100000610793600654876140b4565b905b600254604051636eb1769f60e11b81529060209082906001600160a01b031681806137cb303360048401613ddd565b03915afa90811561058657600091613921575b509161385461383360ff6000996138ba956137fd8660209910156143bc565b60c083901b1916600560c01b17600489018190556001600160801b03199091166001600160801b038a1617885560a01c16614251565b60048601805460ff60a01b191660a09290921b60ff60a01b16919091179055565b60048401805460ff60b81b1916600160b81b17905560095461387690426140c7565b60018501556003840161388a8782546140c7565b90556002546040516323b872dd60e01b81529788936001600160a01b03909216928492839130336004850161411f565b03925af1908115610586576138e9610a5d92600080516020614fbd833981519152966000916126e65750613e61565b6002015460809790970151955160405133986001600160a01b039889169891958695909390921691906001600160801b0316856141a2565b919290506020823d602011613953575b8161393e60209383613dbc565b810103126101fc5790519091906138546137de565b3d9150613931565b6020602491604097949397519283809263179c54c560e31b82523360048301525afa908115610586576000916139d5575b5060e08a015115159015151415806139c6575b1561379c579093506139c068056bc75e2d63100000610793600754876140b4565b9061379c565b5060ff60085460101c1661399f565b6139ee915060203d60201161057f576105718183613dbc565b8a61398c565b5060ff60085460081c1661377a565b613a1c915060203d60201161057f576105718183613dbc565b8b613768565b60405162461bcd60e51b815260206004820152600360248201526245333160e81b6044820152606490fd5b60405162461bcd60e51b815260206004820152600360248201526245323960e81b6044820152606490fd5b5082546001600160801b03908116908216116136e7565b50825460801c6001600160801b038216106136e1565b600591501488610462565b60405162461bcd60e51b815260206004820152600360248201526208a64760eb1b6044820152606490fd5b346101fc5760003660031901126101fc57613af4614f03565b7fc8f30eec0e1dbf4dae4cec56a5b704ebbea51decde007150a6ac1e9a57287999604060085460ff8082161516809160ff19161760085581519033825215156020820152a1005b346101fc5760003660031901126101fc576020600654604051908152f35b346101fc5760203660031901126101fc577ff4b0798d7b6a2458406c2a43f010c1ebdb4f7bb1b3bea5b72360847b353543886102c1600435613b99614f03565b806009556040519182913383614141565b346101fc5760203660031901126101fc576004356000526001602052602060ff604060002054166040519015158152f35b346101fc5760203660031901126101fc576004358015158091036101fc5760407f308e0d1eee69d9ea2239cf57381e00aa26edecbafd04c10f11f90529a327466091613c25614f03565b60ff19600e541660ff821617600e558151908152336020820152a1005b346101fc5760203660031901126101fc576001600160a01b03613c63613ca4565b16600052600d602052602060ff604060002054166040519015158152f35b346101fc5760003660031901126101fc5760209060ff60085460081c1615158152f35b600435906001600160a01b03821682036101fc57565b602435906001600160a01b03821682036101fc57565b602435906001600160801b03821682036101fc57565b600435906001600160801b03821682036101fc57565b60609060031901126101fc57600435906024356001600160801b03811681036101fc57906044356001600160a01b03811681036101fc5790565b90600a8210156105e05752565b8054821015613d5b5760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b61010081019081106001600160401b03821117610a8157604052565b61016081019081106001600160401b03821117610a8157604052565b6001600160401b038111610a8157604052565b90601f801991011681019081106001600160401b03821117610a8157604052565b6001600160a01b0391821681529116602082015260400190565b908160209103126101fc575180151581036101fc5790565b600a8210156105e05752565b80546001600160801b031660809290921b6001600160801b031916919091179055565b6001600160a01b0390911681526001600160801b03909116602082015260400190565b15613e6857565b60405162461bcd60e51b815260206004820152600360248201526245343160e81b6044820152606490fd5b600260005414613ea4576002600055565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b600354604051630935e01b60e21b81523360048201526020916001600160a01b0316908281602481855afa918215610586578391600093613fca575b508215613f60575b505015613f375750565b6064906040519062461bcd60e51b825260048201526002602482015261229960f11b6044820152fd5b604051636c46138f60e11b81523360048201529250829060249082905afa801561058657600090613f99575b60c8915011158138613f2d565b8282813d8311613fc3575b613fae8183613dbc565b81010312613fc0575060c89051613f8c565b80fd5b503d613fa4565b613fe2919350823d841161057f576105718183613dbc565b9138613f25565b15613ff057565b60405162461bcd60e51b815260206004820152600360248201526245313160e81b6044820152606490fd5b1561402257565b60405162461bcd60e51b8152602060048201526003602482015262114c4d60ea1b6044820152606490fd5b1561405457565b606460405162461bcd60e51b815260206004820152602060248201527f4f6e6c792052656c61746564205573657220507572636861736520546f6b656e6044820152fd5b6001600160801b039182169082160290811691908203611ae557565b81810292918115918404141715611ae557565b91908201809211611ae557565b6001600160801b039182169082160391908211611ae557565b156140f457565b60405162461bcd60e51b815260206004820152600360248201526245313560e81b6044820152606490fd5b6001600160a01b03918216815291166020820152604081019190915260600190565b6001600160a01b039091168152602081019190915260400190565b91908203918211611ae557565b6001600160801b039182168152911660208201526001600160a01b03918216604082015291166060820152608081019190915260a00190565b6001600160801b039182168152911660208201526001600160a01b039091166040820152606081019190915260800190565b156141db57565b60405162461bcd60e51b815260206004820152600360248201526204534360ec1b6044820152606490fd5b1561420d57565b60405162461bcd60e51b815260206004820152600360248201526222991960e91b6044820152606490fd5b6001600160801b039182169082160191908211611ae557565b60ff1660ff8114611ae55760010190565b6000526020600a81526040602481600020825161427e81613d71565b815460018060801b0390818116835260801c8683015260018301549081168583015260801c606082015260018060a01b039060e060ff6003846002870154169560808501968752015484811660a08501526142e1828260a01c1660c08601613e0f565b60a81c161515910152848160035416855194858092630935e01b60e21b82523360048301525afa92831561437f57600093614360575b508215614352575b50501561432a575050565b60649250519062461bcd60e51b825260048201526002602482015261453360f01b6044820152fd5b90511633149050388061431f565b614378919350853d871161057f576105718183613dbc565b9138614317565b84513d6000823e3d90fd5b1561439157565b60405162461bcd60e51b815260206004820152600360248201526245323160e81b6044820152606490fd5b156143c357565b60405162461bcd60e51b815260206004820152600360248201526222989b60e91b6044820152606490fd5b600354604051630935e01b60e21b815233600482015260209290916001600160a01b03919084908490602490829086165afa92831561058657600093614494575b50821561446a575b5050156144415750565b6064906040519062461bcd60e51b825260048201526002602482015261114d60f21b6044820152fd5b90915033600052600b83526040600020906000528252339060046040600020015416143880614437565b6144ac919350843d861161057f576105718183613dbc565b913861442f565b80600052600c60205260406000205460005b8181106144d157505050565b82600052600c6020526144e8816040600020613d43565b905460018060a01b039160031b1c16600052600b602052604060002083600052602052604060002090600a60205260406000209160036040519361452b85613d71565b805460018060801b038116865260801c6020860152600181015460018060801b038116604087015260801c606086015260018060a01b036002820154166080860152015460a060018060a01b0382168186015260ff8261459482809560c0951c16848901613e0f565b60a81c16151560e0860152600283015460408601516060909601516001600160801b03918216966145c9918316908316614238565b16851191826146e7575b50506145e5575b5060019150016144c5565b6146a39260209186600052600c835261463a61462f614608866040600020613d43565b9054845460039290921b1c6001600160a01b0316946001600160801b0391909116906140b4565b6003830154906140c7565b916004809201600160c31b60ff60c01b1982541617905587600052600c8452614667856040600020613d43565b81549060018060a01b039060031b1b19169055600060018060a01b0360025416926040519788958694859363a9059cbb60e01b85528401614141565b03925af1918215610586576001926146c2916000916146c85750613e61565b386145da565b6146e1915060203d60201161057f576105718183613dbc565b3861052b565b90915060049182840154901c16600a811015614705571438806145d3565b602182634e487b7160e01b6000525260246000fd5b600090808252602091600a83526040918282209083519161473a83613d71565b614845815460018060801b0390818116865260801c8886015260018301548181168887015260801c606086015260018060a01b0393600385600286015416946080880195865201549585871660a082015260e060ff886147a382809b60a01c1660c08601613e0f565b60a81c161515910152338752600b8952878720908752885261014060048888208951936147cf85613d8d565b8154818116865260801c8c86015260018201548b86015260028201541660608501526003810154608085015201549560a08301968681168852818160a01c1660c0850152818160a81c1660e0850152818160b01c161515610100850152818160b81c16151561012085015260c01c169101613e0f565b6024868360035416875192838092630935e01b60e21b82523360048301525afa9485156148ef57946148d0575b5083156148c3575b5082156148b5575b50501561488d575050565b60649250519062461bcd60e51b825260048201526002602482015261453560f01b6044820152fd5b905116331490503880614882565b518116331492503861487a565b6148e8919450863d881161057f576105718183613dbc565b9238614872565b8651903d90823e3d90fd5b6001600160401b038111610a815760051b60200190565b81601f820112156101fc57805191614928836148fa565b926149366040519485613dbc565b808452602092838086019260051b8201019283116101fc578301905b828210614960575050505090565b81518152908301908301614952565b8051821015613d5b5760209160051b010190565b60018060a01b0360045416906040519063ff227f5b60e01b8252600082806149af848860048401613ddd565b0381865afa92831561058657600092600094614e14575b50600060405180926329c7cb6b60e21b825281806149e8878b60048401613ddd565b03915afa94851561058657600091600096614db6575b5083519586614a12575b5050505050505090565b90929496919395976000925b6001600160801b0384168a1115614da7578015614d905780614a496001600160801b0386168561496f565b5111614c2757614a6d90614a666001600160801b0386168b61496f565b519061415c565b6002549093906001600160a01b0390811690614a926001600160801b0384168b61496f565b511690614aa86001600160801b0384168c61496f565b5191604051809263a9059cbb60e01b825281600081614ace602098899760048401614141565b03925af190811561058657614aeb92600092614c0a575050613e61565b6004546001600160a01b0316614b0a6001600160801b0383168861496f565b51813b156101fc5760405163ef974bc160e01b81526001600160a01b038816600482015260248101919091526000604482018190526001606483015290918290608490829084905af1801561058657614bfb575b507fad4c78a4c10700baa16b8f1405092d6a4b234f9cced291f624d221a4edf016ca85614b946001600160801b0384168c61496f565b51614be56001600160a01b03614bb36001600160801b0387168e61496f565b51604080519485526001600160a01b038e81166020870152958616908501521690921660608201529081906080820190565b0390a15b6001016001600160801b031692614a1e565b614c0490613da9565b38614b5e565b614c209250803d1061057f576105718183613dbc565b3880613481565b9283614c3c6001600160801b0383168561496f565b511115614be957614c6084614c5a6001600160801b0384168c61496f565b5161415c565b600094614caf60208260018060a01b03600254168d614c8f60018060a01b039160018060801b038a169061496f565b5116600060405180968195829463a9059cbb60e01b845260048401614141565b03925af1801561058657614cca916000916146c85750613e61565b6004546001600160a01b0316614ce96001600160801b0385168a61496f565b51813b156101fc5760848960008094604051978895869463ef974bc160e01b865260018060a01b0316600486015260248501526044840152600260648401525af1908115610586577fad4c78a4c10700baa16b8f1405092d6a4b234f9cced291f624d221a4edf016ca928892614d81575b50614d796001600160a01b03614bb36001600160801b0387168e61496f565b0390a1614be9565b614d8a90613da9565b38614d5a565b975097505050505050505b38808080808080614a08565b97509750505050505050614d9b565b915094503d806000833e614dca8183613dbc565b8101906040818303126101fc578051916001600160401b03928381116101fc5781614df6918401614911565b9260208301519081116101fc57614e0d9201614911565b94386149fe565b925092503d806000843e614e288184613dbc565b82016080838203126101fc578251926001600160401b03938481116101fc5781019180601f840112156101fc578251614e60816148fa565b93614e6e6040519586613dbc565b818552602091828087019160051b830101918483116101fc578301905b828210614ee4575050508201518581116101fc5781614eab918401614911565b9460408301518181116101fc5782614ec4918501614911565b5060608301519081116101fc57614edb9201614911565b509192386149c6565b81516001600160a01b03811681036101fc578152908301908301614e8b565b600354604051630935e01b60e21b815233600482015290602090829060249082906001600160a01b03165afa90811561058657600091614f70575b5015614f4657565b60405162461bcd60e51b8152602060048201526002602482015261453160f01b6044820152606490fd5b614f88915060203d811161057f576105718183613dbc565b38614f3e565b6002815261555360f01b602082015260400190565b60068152654e6f6e2d555360d01b60208201526040019056fede1918fb2f2e3731c3f6ce96b42b3f1019be43e553400564a8616b299bea7294a2646970667358221220114f99da1939fc9d565bd75358af05757d116b00b3f2affe2d9dd33df12cf0ff64736f6c634300081300330000000000000000000000008ad514e520eab3b6e4e6dbc4d52e82b526c33b4200000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a11700000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a117
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008ad514e520eab3b6e4e6dbc4d52e82b526c33b4200000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a11700000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a117
-----Decoded View---------------
Arg [0] : stableCoinAddress (address): 0x8ad514e520eab3b6e4e6dbc4d52e82b526c33b42
Arg [1] : whitelistingAddress (address): 0x94278f999745826cc0266e3bea85a9d5c2c8a117
Arg [2] : marginLoanAddress (address): 0x94278f999745826cc0266e3bea85a9d5c2c8a117
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000008ad514e520eab3b6e4e6dbc4d52e82b526c33b42
Arg [1] : 00000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a117
Arg [2] : 00000000000000000000000094278f999745826cc0266e3bea85a9d5c2c8a117
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|