Transaction Hash:
Block:
13549116 at Nov-04-2021 08:22:00 AM +UTC
Transaction Fee:
0.01972371396233415 ETH
$42.20
Gas Used:
200,105 Gas / 98.56682223 Gwei
Emitted Events:
| 421 |
UniqueUtilityToken.Transfer( from=0xD74902b67d4429A50791033b4bDFEA41a7D0Bce7, to=[Sender] 0xd4c1c2e157c8f3cd5d76b856f3306dbaab3d8022, value=1912000000000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x829BD824...93333A830
Miner
| (F2Pool Old) | 949.788537702162177128 Eth | 949.788757763652837103 Eth | 0.000220061490659975 | |
| 0xa80f2C8f...e72c45d4C | |||||
| 0xBBEa1eBD...13711C377 | |||||
| 0xD4C1C2E1...AAb3d8022 |
0.042422014033228 Eth
Nonce: 1
|
0.02269830007089385 Eth
Nonce: 2
| 0.01972371396233415 |
Execution Trace
TransferExclusive.transferExclusive( ) => ( 1 )
-
UniqueUtilityToken.allowance( tokenOwner=0xD74902b67d4429A50791033b4bDFEA41a7D0Bce7, spender=0xBBEa1eBD631862A1686205860d6E79913711C377 ) => ( remaining=31952689000000000000000000 )
-
UniqueUtilityToken.transferFrom( from=0xD74902b67d4429A50791033b4bDFEA41a7D0Bce7, to=0xD4C1C2E157C8f3CD5d76b856f3306dbAAb3d8022, tokens=1912000000000000000000 ) => ( success=True )
transferExclusive[TransferExclusive (ln:139)]
allowance[TransferExclusive (ln:140)]encode[TransferExclusive (ln:142)]toAsciiString[TransferExclusive (ln:142)]uint2str[TransferExclusive (ln:142)]verify[TransferExclusive (ln:144)]_internalTransferFrom[TransferExclusive (ln:148)]transferFrom[TransferExclusive (ln:154)]
File 1 of 2: TransferExclusive
File 2 of 2: UniqueUtilityToken
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
//SPDX-License-Identifier: MIT
interface IERC20 {
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner, "Only for owner");
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract TransferExclusive is Ownable {
IERC20 public _tokenContract;
address public _tokenAddress;
address public _ownerAddress;
mapping (address => uint256) claims;
bytes32 _merkleRoot;
struct inputModel {
address addr;
uint64 val;
}
constructor (address contractAddress, address ownerAddress) {
_tokenContract = IERC20(contractAddress);
_ownerAddress = ownerAddress;
_tokenAddress = contractAddress;
}
function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len;
while (_i != 0) {
k = k-1;
uint8 temp = (48 + uint8(_i - _i / 10 * 10));
bytes1 b1 = bytes1(temp);
bstr[k] = b1;
_i /= 10;
}
return string(bstr);
}
function toAsciiString(address x) internal pure returns (string memory) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i)))));
bytes1 hi = bytes1(uint8(b) / 16);
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
s[2*i] = char(hi);
s[2*i+1] = char(lo);
}
return string(s);
}
function char(bytes1 b) internal pure returns (bytes1 c) {
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
else return bytes1(uint8(b) + 0x57);
}
function verify(bytes32 root, bytes32 leaf, bytes32[] memory proof) private pure returns (bool)
{
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash < proofElement) {
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash == root;
}
function setMerkleRoot(bytes32 merkleRoot) public onlyOwner {
_merkleRoot = merkleRoot;
}
function setPrimaryContract(address contractAddress, address ownerAddress) public onlyOwner returns (uint256){
_tokenContract = IERC20(contractAddress);
_ownerAddress = ownerAddress;
_tokenAddress = contractAddress;
return 1;
}
function getPrimaryAllowance() public onlyOwner view returns (uint256){
return _tokenContract.allowance(_ownerAddress, address(this));
}
function getClaimedValue(address _address) public view returns (uint256){
return claims[_address];
}
function transferExclusive(uint256 amount, uint256 max, bytes32[] memory proof) public returns (uint256){
require(_tokenContract.allowance(_ownerAddress, address(this)) >= amount, "Allowance too low");
bytes32 leaf=keccak256(abi.encode(abi.encodePacked("0x",toAsciiString(msg.sender), uint2str(max))));
require(verify(_merkleRoot, leaf, proof), "Verify failed");
require(claims[msg.sender]+amount <= max, "Amount not allowed");
_internalTransferFrom(_tokenContract, _ownerAddress, msg.sender, amount);
return 1;
}
function _internalTransferFrom(IERC20 token, address sender, address recipient, uint256 amount) private {
bool sent = token.transferFrom(sender, recipient, amount*100000000000000);
require(sent, "Token transfer failed");
claims[recipient]+=amount;
}
}File 2 of 2: UniqueUtilityToken
pragma solidity 0.8.3;
// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
c = a * b;
require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
require(b > 0);
c = a / b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
//
// Borrowed from MiniMeToken
// ----------------------------------------------------------------------------
abstract contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes memory data) virtual public;
}
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed _from, address indexed _to);
constructor() {
owner = 0xC7781bf45EE2C64AA6E330Bd0e35522C1d7BA6b3;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
contract UniqueUtilityToken is IERC20, Owned, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor() {
name = "Unique Utility Token";
symbol = "UNQT";
decimals = 18;
_totalSupply = 100000000e18; // 100,000,000 UNQT
address owner = owner;
balances[owner] = _totalSupply;
emit Transfer(address(0), owner, _totalSupply);
}
// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------
function totalSupply() public view override returns (uint) {
return _totalSupply;
}
// ------------------------------------------------------------------------
// Get the token balance for account tokenOwner
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public view override returns (uint balance) {
return balances[tokenOwner];
}
// ------------------------------------------------------------------------
// Transfer the balance from token owner's account to to account
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transfer(address to, uint tokens) public override returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
Transfer(msg.sender, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public virtual override returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
return true;
}
// ------------------------------------------------------------------------
// Transfer tokens from the from account to the to account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from the from account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address from, address to, uint tokens) public virtual override returns (bool success) {
balances[from] = safeSub(balances[from], tokens);
allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
balances[to] = safeAdd(balances[to], tokens);
Transfer(from, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public view virtual override returns (uint remaining) {
return allowed[tokenOwner][spender];
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account. The spender contract function
// receiveApproval(...) is then executed
// ------------------------------------------------------------------------
function approveAndCall(address spender, uint tokens, bytes memory data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, address(this), data);
return true;
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
receive () external payable {
revert();
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return IERC20(tokenAddress).transfer(owner, tokens);
}
}