Transaction Hash:
Block:
16314148 at Jan-01-2023 07:56:23 PM +UTC
Transaction Fee:
0.001627765885899492 ETH
$3.39
Gas Used:
96,108 Gas / 16.936840699 Gwei
Emitted Events:
| 182 |
NBU.Transfer( from=[Sender] 0x702ddc27ee80d3f89ebcc7e6c63243ea0ecb53f7, to=[Receiver] ERC20ToBEP20Wrapper, value=4971188100000000000000 )
|
| 183 |
NBU.Approval( owner=[Sender] 0x702ddc27ee80d3f89ebcc7e6c63243ea0ecb53f7, spender=[Receiver] ERC20ToBEP20Wrapper, value=115792089237316195423570985008687907853269984665640564034486395907913129639935 )
|
| 184 |
ERC20ToBEP20Wrapper.Wrap( user=[Sender] 0x702ddc27ee80d3f89ebcc7e6c63243ea0ecb53f7, wrapNonce=1, amount=4971188100000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x690B9A9E...Db4FaC990
Miner
| (builder0x69) | 1.925055360201336855 Eth | 1.925295630201336855 Eth | 0.00024027 | |
| 0x702DdC27...a0eCB53F7 |
0.152403790006012204 Eth
Nonce: 52
|
0.150776024120112712 Eth
Nonce: 53
| 0.001627765885899492 | ||
| 0xBFe52A0D...4BF19368E | |||||
| 0xEB58343b...241310049 |
Execution Trace
ERC20ToBEP20Wrapper.wrap( amount=4971188100000000000000 )
-
NBU.transferFrom( sender=0x702DdC27eE80D3F89ebcC7E6c63243ea0eCB53F7, recipient=0xBFe52A0DBF40183bc5fC3220Dab2Db64BF19368E, amount=4971188100000000000000 ) => ( True )
File 1 of 2: ERC20ToBEP20Wrapper
File 2 of 2: NBU
pragma solidity =0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address to, 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 Ownable {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed from, address indexed to);
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), owner);
}
modifier onlyOwner {
require(msg.sender == owner, "Ownable: Caller is not the owner");
_;
}
function transferOwnership(address transferOwner) external onlyOwner {
require(transferOwner != newOwner);
newOwner = transferOwner;
}
function acceptOwnership() virtual public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
contract ERC20ToBEP20Wrapper is Ownable {
struct UnwrapInfo {
uint amount;
uint fee;
uint bscNonce;
}
IERC20 public immutable NBU;
uint public minWrapAmount;
mapping(address => uint) public userWrapNonces;
mapping(address => uint) public userUnwrapNonces;
mapping(address => mapping(uint => uint)) public bscToEthUserUnwrapNonces;
mapping(address => mapping(uint => uint)) public wraps;
mapping(address => mapping(uint => UnwrapInfo)) public unwraps;
event Wrap(address indexed user, uint indexed wrapNonce, uint amount);
event Unwrap(address indexed user, uint indexed unwrapNonce, uint indexed bscNonce, uint amount, uint fee);
event UpdateMinWrapAmount(uint indexed amount);
event Rescue(address indexed to, uint amount);
event RescueToken(address token, address indexed to, uint amount);
constructor(address nbu) {
NBU = IERC20(nbu);
}
function wrap(uint amount) external {
require(amount >= minWrapAmount, "ERC20ToBEP20Wrapper: Value too small");
NBU.transferFrom(msg.sender, address(this), amount);
uint userWrapNonce = ++userWrapNonces[msg.sender];
wraps[msg.sender][userWrapNonce] = amount;
emit Wrap(msg.sender, userWrapNonce, amount);
}
function unwrap(address user, uint amount, uint fee, uint bscNonce) external onlyOwner {
require(user != address(0), "ERC20ToBEP20Wrapper: Can't be zero address");
require(bscToEthUserUnwrapNonces[user][bscNonce] == 0, "ERC20ToBEP20Wrapper: Already processed");
NBU.transfer(user, amount - fee);
uint unwrapNonce = ++userUnwrapNonces[user];
bscToEthUserUnwrapNonces[user][bscNonce] = unwrapNonce;
unwraps[user][unwrapNonce].amount = amount;
unwraps[user][unwrapNonce].fee = fee;
unwraps[user][unwrapNonce].bscNonce = bscNonce;
emit Unwrap(user, unwrapNonce, bscNonce, amount, fee);
}
//Admin functions
function rescue(address payable to, uint256 amount) external onlyOwner {
require(to != address(0), "ERC20ToBEP20Wrapper: Can't be zero address");
require(amount > 0, "ERC20ToBEP20Wrapper: Should be greater than 0");
TransferHelper.safeTransferETH(to, amount);
emit Rescue(to, amount);
}
function rescue(address to, address token, uint256 amount) external onlyOwner {
require(to != address(0), "ERC20ToBEP20Wrapper: Can't be zero address");
require(amount > 0, "ERC20ToBEP20Wrapper: Should be greater than 0");
TransferHelper.safeTransfer(token, to, amount);
emit RescueToken(token, to, amount);
}
function updateMinWrapAmount(uint amount) external onlyOwner {
require(amount > 0, "ERC20ToBEP20Wrapper: Should be greater than 0");
minWrapAmount = amount;
emit UpdateMinWrapAmount(amount);
}
}File 2 of 2: NBU
pragma solidity =0.8.0;
// ----------------------------------------------------------------------------
// NBU token main contract (2020)
//
// Symbol : NBU
// Name : Nimbus
// Total supply : 1.000.000.000 (burnable)
// Decimals : 18
// ----------------------------------------------------------------------------
// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
interface IERC20 {
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 Ownable {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed from, address indexed to);
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), owner);
}
modifier onlyOwner {
require(msg.sender == owner, "Ownable: Caller is not the owner");
_;
}
function transferOwnership(address transferOwner) public onlyOwner {
require(transferOwner != newOwner);
newOwner = transferOwner;
}
function acceptOwnership() virtual public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
modifier whenNotPaused() {
require(!paused);
_;
}
modifier whenPaused() {
require(paused);
_;
}
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return add(a, b, "SafeMath: addition overflow");
}
function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
contract NBU is IERC20, Ownable, Pausable {
using SafeMath for uint;
mapping (address => mapping (address => uint)) private _allowances;
mapping (address => uint) private _unfrozenBalances;
mapping (address => uint) private _vestingNonces;
mapping (address => mapping (uint => uint)) private _vestingAmounts;
mapping (address => mapping (uint => uint)) private _unvestedAmounts;
mapping (address => mapping (uint => uint)) private _vestingTypes; //0 - multivest, 1 - single vest, > 2 give by vester id
mapping (address => mapping (uint => uint)) private _vestingReleaseStartDates;
uint private _totalSupply = 1_000_000_000e18;
string private constant _name = "Nimbus";
string private constant _symbol = "NBU";
uint8 private constant _decimals = 18;
uint private vestingFirstPeriod = 60 days;
uint private vestingSecondPeriod = 152 days;
uint public giveAmount;
mapping (address => bool) public vesters;
bytes32 public immutable DOMAIN_SEPARATOR;
bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
mapping (address => uint) public nonces;
event Unvest(address user, uint amount);
constructor () {
_unfrozenBalances[owner] = _totalSupply;
emit Transfer(address(0), owner, _totalSupply);
uint chainId = block.chainid;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,uint256 chainId,address verifyingContract)'),
keccak256(bytes(_name)),
chainId,
address(this)
)
);
giveAmount = _totalSupply / 10;
}
function approve(address spender, uint amount) external override whenNotPaused returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transfer(address recipient, uint amount) external override whenNotPaused returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function transferFrom(address sender, address recipient, uint amount) external override whenNotPaused returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "NBU::transferFrom: transfer amount exceeds allowance"));
return true;
}
function permit(address owner, address spender, uint amount, uint deadline, uint8 v, bytes32 r, bytes32 s) external whenNotPaused {
bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, amount, nonces[owner]++, deadline));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "NBU::permit: invalid signature");
require(signatory == owner, "NBU::permit: unauthorized");
require(block.timestamp <= deadline, "NBU::permit: signature expired");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function increaseAllowance(address spender, uint addedValue) external returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint subtractedValue) external returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "NBU::decreaseAllowance: decreased allowance below zero"));
return true;
}
function unvest() external whenNotPaused returns (uint unvested) {
require (_vestingNonces[msg.sender] > 0, "NBU::unvest:No vested amount");
for (uint i = 1; i <= _vestingNonces[msg.sender]; i++) {
if (_vestingAmounts[msg.sender][i] == _unvestedAmounts[msg.sender][i]) continue;
if (_vestingReleaseStartDates[msg.sender][i] > block.timestamp) break;
uint toUnvest = block.timestamp.sub(_vestingReleaseStartDates[msg.sender][i]).mul(_vestingAmounts[msg.sender][i]) / vestingSecondPeriod;
if (toUnvest > _vestingAmounts[msg.sender][i]) {
toUnvest = _vestingAmounts[msg.sender][i];
}
uint totalUnvestedForNonce = toUnvest;
toUnvest = toUnvest.sub(_unvestedAmounts[msg.sender][i]);
unvested = unvested.add(toUnvest);
_unvestedAmounts[msg.sender][i] = totalUnvestedForNonce;
}
_unfrozenBalances[msg.sender] = _unfrozenBalances[msg.sender].add(unvested);
emit Unvest(msg.sender, unvested);
}
function give(address user, uint amount, uint vesterId) external {
require (giveAmount > amount, "NBU::give: give finished");
require (vesters[msg.sender], "NBU::give: not vester");
giveAmount = giveAmount.sub(amount);
_vest(user, amount, vesterId);
}
function vest(address user, uint amount) external {
require (vesters[msg.sender], "NBU::vest: not vester");
_vest(user, amount, 1);
}
function burnTokens(uint amount) external onlyOwner returns (bool success) {
require(amount <= _unfrozenBalances[owner], "NBU::burnTokens: exceeds available amount");
_unfrozenBalances[owner] = _unfrozenBalances[owner].sub(amount, "NBU::burnTokens: transfer amount exceeds balance");
_totalSupply = _totalSupply.sub(amount, "NBU::burnTokens: overflow");
emit Transfer(owner, address(0), amount);
return true;
}
function allowance(address owner, address spender) external view override returns (uint) {
return _allowances[owner][spender];
}
function decimals() external pure returns (uint8) {
return _decimals;
}
function name() external pure returns (string memory) {
return _name;
}
function symbol() external pure returns (string memory) {
return _symbol;
}
function totalSupply() external view override returns (uint) {
return _totalSupply;
}
function balanceOf(address account) external view override returns (uint) {
uint amount = _unfrozenBalances[account];
if (_vestingNonces[account] == 0) return amount;
for (uint i = 1; i <= _vestingNonces[account]; i++) {
amount = amount.add(_vestingAmounts[account][i]).sub(_unvestedAmounts[account][i]);
}
return amount;
}
function availableForUnvesting(address user) external view returns (uint unvestAmount) {
if (_vestingNonces[user] == 0) return 0;
for (uint i = 1; i <= _vestingNonces[user]; i++) {
if (_vestingAmounts[user][i] == _unvestedAmounts[user][i]) continue;
if (_vestingReleaseStartDates[user][i] > block.timestamp) break;
uint toUnvest = block.timestamp.sub(_vestingReleaseStartDates[user][i]).mul(_vestingAmounts[user][i]) / vestingSecondPeriod;
if (toUnvest > _vestingAmounts[user][i]) {
toUnvest = _vestingAmounts[user][i];
}
toUnvest = toUnvest.sub(_unvestedAmounts[user][i]);
unvestAmount = unvestAmount.add(toUnvest);
}
}
function availableForTransfer(address account) external view returns (uint) {
return _unfrozenBalances[account];
}
function vestingInfo(address user, uint nonce) external view returns (uint vestingAmount, uint unvestedAmount, uint vestingReleaseStartDate, uint vestType) {
vestingAmount = _vestingAmounts[user][nonce];
unvestedAmount = _unvestedAmounts[user][nonce];
vestingReleaseStartDate = _vestingReleaseStartDates[user][nonce];
vestType = _vestingTypes[user][nonce];
}
function vestingNonces(address user) external view returns (uint lastNonce) {
return _vestingNonces[user];
}
function _approve(address owner, address spender, uint amount) private {
require(owner != address(0), "NBU::_approve: approve from the zero address");
require(spender != address(0), "NBU::_approve: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(address sender, address recipient, uint amount) private {
require(sender != address(0), "NBU::_transfer: transfer from the zero address");
require(recipient != address(0), "NBU::_transfer: transfer to the zero address");
_unfrozenBalances[sender] = _unfrozenBalances[sender].sub(amount, "NBU::_transfer: transfer amount exceeds balance");
_unfrozenBalances[recipient] = _unfrozenBalances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _vest(address user, uint amount, uint vestType) private {
uint nonce = ++_vestingNonces[user];
_vestingAmounts[user][nonce] = amount;
_vestingReleaseStartDates[user][nonce] = block.timestamp + vestingFirstPeriod;
_unfrozenBalances[owner] = _unfrozenBalances[owner].sub(amount);
_vestingTypes[user][nonce] = vestType;
emit Transfer(owner, user, amount);
}
function multisend(address[] memory to, uint[] memory values) external onlyOwner returns (uint) {
require(to.length == values.length);
require(to.length < 100);
uint sum;
for (uint j; j < values.length; j++) {
sum += values[j];
}
_unfrozenBalances[owner] = _unfrozenBalances[owner].sub(sum, "NBU::multisend: transfer amount exceeds balance");
for (uint i; i < to.length; i++) {
_unfrozenBalances[to[i]] = _unfrozenBalances[to[i]].add(values[i], "NBU::multisend: transfer amount exceeds balance");
emit Transfer(owner, to[i], values[i]);
}
return(to.length);
}
function multivest(address[] memory to, uint[] memory values) external onlyOwner returns (uint) {
require(to.length == values.length);
require(to.length < 100);
uint sum;
for (uint j; j < values.length; j++) {
sum += values[j];
}
_unfrozenBalances[owner] = _unfrozenBalances[owner].sub(sum, "NBU::multivest: transfer amount exceeds balance");
for (uint i; i < to.length; i++) {
uint nonce = ++_vestingNonces[to[i]];
_vestingAmounts[to[i]][nonce] = values[i];
_vestingReleaseStartDates[to[i]][nonce] = block.timestamp + vestingFirstPeriod;
_vestingTypes[to[i]][nonce] = 0;
emit Transfer(owner, to[i], values[i]);
}
return(to.length);
}
function updateVesters(address vester, bool isActive) external onlyOwner {
vesters[vester] = isActive;
}
function updateGiveAmount(uint amount) external onlyOwner {
require (_unfrozenBalances[owner] > amount, "NBU::updateGiveAmount: exceed owner balance");
giveAmount = amount;
}
function transferAnyERC20Token(address tokenAddress, uint tokens) external onlyOwner returns (bool success) {
return IERC20(tokenAddress).transfer(owner, tokens);
}
function acceptOwnership() public override {
uint amount = _unfrozenBalances[owner];
_unfrozenBalances[newOwner] = amount;
_unfrozenBalances[owner] = 0;
emit Transfer(owner, newOwner, amount);
super.acceptOwnership();
}
}