Transaction Hash:
Block:
4821743 at Dec-30-2017 03:05:36 AM +UTC
Transaction Fee:
0.0003926075625 ETH
$0.79
Gas Used:
41,057 Gas / 9.5625 Gwei
Emitted Events:
| 125 |
AGT.Transfer( from=[Sender] 0x6ca06fc8a8f0098c00babb18df0efd3c650cddd8, to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, value=5000000000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x6CA06FC8...C650CddD8 |
0.001 Eth
Nonce: 0
|
0.0006073924375 Eth
Nonce: 1
| 0.0003926075625 | ||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 700.65348918675681643 Eth | 700.65388179431931643 Eth | 0.0003926075625 | |
| 0xEd1eba8B...50c85a010 |
Execution Trace
AGT.transfer( dst=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, wad=5000000000000000000 ) => ( True )
SwapController.onTransfer( _from=0x6CA06FC8A8f0098C00baBb18dF0efD3C650CddD8, _to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, _amount=5000000000000000000 ) => ( True )-
AGT2ATNSwap.onTokenTransfer( _from=0x6CA06FC8A8f0098C00baBb18dF0efD3C650CddD8, _to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, _amount=5000000000000000000 ) => ( True ) -
ATNLongTermHolding.onTokenTransfer( _from=0x6CA06FC8A8f0098C00baBb18dF0efD3C650CddD8, _to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, _amount=5000000000000000000 ) => ( True ) -
ATNLongTermHolding.onTokenTransfer( _from=0x6CA06FC8A8f0098C00baBb18dF0efD3C650CddD8, _to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, _amount=5000000000000000000 ) => ( True ) -
ATNLongTermHolding.onTokenTransfer( _from=0x6CA06FC8A8f0098C00baBb18dF0efD3C650CddD8, _to=0x0eCd86d531Cb01faa71fE8661affb26Ef837FFC4, _amount=5000000000000000000 ) => ( True )
-
transfer[AGT (ln:462)]
transferFrom[AGT (ln:469)]isContract[AGT (ln:401)]onTransfer[AGT (ln:402)]transferFrom[AGT (ln:406)]isContract[AGT (ln:408)]call[AGT (ln:411)]ReceivingContractTokenFallbackFailed[AGT (ln:416)]
File 1 of 6: AGT
File 2 of 6: SwapController
File 3 of 6: AGT2ATNSwap
File 4 of 6: ATNLongTermHolding
File 5 of 6: ATNLongTermHolding
File 6 of 6: ATNLongTermHolding
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
contract DSStop is DSNote, DSAuth {
bool public stopped;
modifier stoppable {
require(!stopped);
_;
}
function stop() public auth note {
stopped = true;
}
function start() public auth note {
stopped = false;
}
}
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
contract DSMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x);
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x);
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
function min(uint x, uint y) internal pure returns (uint z) {
return x <= y ? x : y;
}
function max(uint x, uint y) internal pure returns (uint z) {
return x >= y ? x : y;
}
function imin(int x, int y) internal pure returns (int z) {
return x <= y ? x : y;
}
function imax(int x, int y) internal pure returns (int z) {
return x >= y ? x : y;
}
uint constant WAD = 10 ** 18;
uint constant RAY = 10 ** 27;
function wmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, RAY), y / 2) / y;
}
// This famous algorithm is called "exponentiation by squaring"
// and calculates x^n with x as fixed-point and n as regular unsigned.
//
// It's O(log n), instead of O(n) for naive repeated multiplication.
//
// These facts are why it works:
//
// If n is even, then x^n = (x^2)^(n/2).
// If n is odd, then x^n = x * x^(n-1),
// and applying the equation for even x gives
// x^n = x * (x^2)^((n-1) / 2).
//
// Also, EVM division is flooring and
// floor[(n-1) / 2] = floor[n / 2].
//
function rpow(uint x, uint n) internal pure returns (uint z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
contract DSTokenBase is ERC20, DSMath {
uint256 _supply;
mapping (address => uint256) _balances;
mapping (address => mapping (address => uint256)) _approvals;
function DSTokenBase(uint supply) public {
_balances[msg.sender] = supply;
_supply = supply;
}
function totalSupply() public view returns (uint) {
return _supply;
}
function balanceOf(address src) public view returns (uint) {
return _balances[src];
}
function allowance(address src, address guy) public view returns (uint) {
return _approvals[src][guy];
}
function transfer(address dst, uint wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad)
public
returns (bool)
{
if (src != msg.sender) {
_approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
}
_balances[src] = sub(_balances[src], wad);
_balances[dst] = add(_balances[dst], wad);
Transfer(src, dst, wad);
return true;
}
function approve(address guy, uint wad) public returns (bool) {
_approvals[msg.sender][guy] = wad;
Approval(msg.sender, guy, wad);
return true;
}
}
contract DSToken is DSTokenBase(0), DSStop {
mapping (address => mapping (address => bool)) _trusted;
bytes32 public symbol;
uint256 public decimals = 18; // standard token precision. override to customize
function DSToken(bytes32 symbol_) public {
symbol = symbol_;
}
event Trust(address indexed src, address indexed guy, bool wat);
event Mint(address indexed guy, uint wad);
event Burn(address indexed guy, uint wad);
function trusted(address src, address guy) public view returns (bool) {
return _trusted[src][guy];
}
function trust(address guy, bool wat) public stoppable {
_trusted[msg.sender][guy] = wat;
Trust(msg.sender, guy, wat);
}
function approve(address guy, uint wad) public stoppable returns (bool) {
return super.approve(guy, wad);
}
function transferFrom(address src, address dst, uint wad)
public
stoppable
returns (bool)
{
if (src != msg.sender && !_trusted[src][msg.sender]) {
_approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
}
_balances[src] = sub(_balances[src], wad);
_balances[dst] = add(_balances[dst], wad);
Transfer(src, dst, wad);
return true;
}
function push(address dst, uint wad) public {
transferFrom(msg.sender, dst, wad);
}
function pull(address src, uint wad) public {
transferFrom(src, msg.sender, wad);
}
function move(address src, address dst, uint wad) public {
transferFrom(src, dst, wad);
}
function mint(uint wad) public {
mint(msg.sender, wad);
}
function burn(uint wad) public {
burn(msg.sender, wad);
}
function mint(address guy, uint wad) public auth stoppable {
_balances[guy] = add(_balances[guy], wad);
_supply = add(_supply, wad);
Mint(guy, wad);
}
function burn(address guy, uint wad) public auth stoppable {
if (guy != msg.sender && !_trusted[guy][msg.sender]) {
_approvals[guy][msg.sender] = sub(_approvals[guy][msg.sender], wad);
}
_balances[guy] = sub(_balances[guy], wad);
_supply = sub(_supply, wad);
Burn(guy, wad);
}
// Optional token name
bytes32 public name = "";
function setName(bytes32 name_) public auth {
name = name_;
}
}
/// @title ERC223ReceivingContract - Standard contract implementation for compatibility with ERC223 tokens.
contract ERC223ReceivingContract {
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param _from Transaction initiator, analogue of msg.sender
/// @param _value Number of tokens to transfer.
/// @param _data Data containig a function signature and/or parameters
function tokenFallback(address _from, uint256 _value, bytes _data) public;
/// @dev For ERC20 backward compatibility, same with above tokenFallback but without data.
/// The function execution could fail, but do not influence the token transfer.
/// @param _from Transaction initiator, analogue of msg.sender
/// @param _value Number of tokens to transfer.
// function tokenFallback(address _from, uint256 _value) public;
}
/// @dev The token controller contract must implement these functions
contract TokenController {
/// @notice Called when `_owner` sends ether to the MiniMe Token contract
/// @param _owner The address that sent the ether to create tokens
/// @return True if the ether is accepted, false if it throws
function proxyPayment(address _owner) payable public returns(bool);
/// @notice Notifies the controller about a token transfer allowing the
/// controller to react if desired
/// @param _from The origin of the transfer
/// @param _to The destination of the transfer
/// @param _amount The amount of the transfer
/// @return False if the controller does not authorize the transfer
function onTransfer(address _from, address _to, uint _amount) public returns(bool);
/// @notice Notifies the controller about an approval allowing the
/// controller to react if desired
/// @param _owner The address that calls `approve()`
/// @param _spender The spender in the `approve()` call
/// @param _amount The amount in the `approve()` call
/// @return False if the controller does not authorize the approval
function onApprove(address _owner, address _spender, uint _amount) public returns(bool);
}
contract Controlled {
/// @notice The address of the controller is the only address that can call
/// a function with this modifier
modifier onlyController { if (msg.sender != controller) throw; _; }
address public controller;
function Controlled() { controller = msg.sender;}
/// @notice Changes the controller of the contract
/// @param _newController The new controller of the contract
function changeController(address _newController) onlyController {
controller = _newController;
}
}
contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 _amount, address _token, bytes _data);
}
contract ERC223 {
function transfer(address to, uint amount, bytes data) public returns (bool ok);
function transferFrom(address from, address to, uint256 amount, bytes data) public returns (bool ok);
function transfer(address to, uint amount, bytes data, string custom_fallback) public returns (bool ok);
function transferFrom(address from, address to, uint256 amount, bytes data, string custom_fallback) public returns (bool ok);
event ERC223Transfer(address indexed from, address indexed to, uint amount, bytes data);
event ReceivingContractTokenFallbackFailed(address indexed from, address indexed to, uint amount);
}
contract AGT is DSToken("AGT"), ERC223, Controlled {
function AGT() {
setName("Genesis Token of ATNIO");
}
/// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
/// is approved by `_from`
/// @param _from The address holding the tokens being transferred
/// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred
/// @return True if the transfer was successful
function transferFrom(address _from, address _to, uint256 _amount
) public returns (bool success) {
// Alerts the token controller of the transfer
if (isContract(controller)) {
if (!TokenController(controller).onTransfer(_from, _to, _amount))
throw;
}
success = super.transferFrom(_from, _to, _amount);
if (success && isContract(_to))
{
// ERC20 backward compatiability
if(!_to.call(bytes4(keccak256("tokenFallback(address,uint256)")), _from, _amount)) {
// do nothing when error in call in case that the _to contract is not inherited from ERC223ReceivingContract
// revert();
// bytes memory empty;
ReceivingContractTokenFallbackFailed(_from, _to, _amount);
// Even the fallback failed if there is such one, the transfer will not be revert since "revert()" is not called.
}
}
}
/*
* ERC 223
* Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
*/
function transferFrom(address _from, address _to, uint256 _amount, bytes _data)
public
returns (bool success)
{
// Alerts the token controller of the transfer
if (isContract(controller)) {
if (!TokenController(controller).onTransfer(_from, _to, _amount))
throw;
}
require(super.transferFrom(_from, _to, _amount));
if (isContract(_to)) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.tokenFallback(_from, _amount, _data);
}
ERC223Transfer(_from, _to, _amount, _data);
return true;
}
/*
* ERC 223
* Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
* https://github.com/ethereum/EIPs/issues/223
* function transfer(address _to, uint256 _value, bytes _data) public returns (bool success);
*/
/// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
/// tokenFallback if sender is a contract.
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param _to Address of token receiver.
/// @param _amount Number of tokens to transfer.
/// @param _data Data to be sent to tokenFallback
/// @return Returns success of function call.
function transfer(
address _to,
uint256 _amount,
bytes _data)
public
returns (bool success)
{
return transferFrom(msg.sender, _to, _amount, _data);
}
/*
* ERC 223
* Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
*/
function transferFrom(address _from, address _to, uint256 _amount, bytes _data, string _custom_fallback)
public
returns (bool success)
{
// Alerts the token controller of the transfer
if (isContract(controller)) {
if (!TokenController(controller).onTransfer(_from, _to, _amount))
throw;
}
require(super.transferFrom(_from, _to, _amount));
if (isContract(_to)) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.call.value(0)(bytes4(keccak256(_custom_fallback)), _from, _amount, _data);
}
ERC223Transfer(_from, _to, _amount, _data);
return true;
}
/*
* ERC 223
* Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
*/
function transfer(
address _to,
uint _amount,
bytes _data,
string _custom_fallback)
public
returns (bool success)
{
return transferFrom(msg.sender, _to, _amount, _data, _custom_fallback);
}
/// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
/// its behalf. This is a modified version of the ERC20 approve function
/// to be a little bit safer
/// @param _spender The address of the account able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer
/// @return True if the approval was successful
function approve(address _spender, uint256 _amount) returns (bool success) {
// Alerts the token controller of the approve function call
if (isContract(controller)) {
if (!TokenController(controller).onApprove(msg.sender, _spender, _amount))
throw;
}
return super.approve(_spender, _amount);
}
function mint(address _guy, uint _wad) auth stoppable {
super.mint(_guy, _wad);
Transfer(0, _guy, _wad);
}
function burn(address _guy, uint _wad) auth stoppable {
super.burn(_guy, _wad);
Transfer(_guy, 0, _wad);
}
/// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
/// its behalf, and then a function is triggered in the contract that is
/// being approved, `_spender`. This allows users to use their tokens to
/// interact with contracts in one function call instead of two
/// @param _spender The address of the contract able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer
/// @return True if the function call was successful
function approveAndCall(address _spender, uint256 _amount, bytes _extraData
) returns (bool success) {
if (!approve(_spender, _amount)) throw;
ApproveAndCallFallBack(_spender).receiveApproval(
msg.sender,
_amount,
this,
_extraData
);
return true;
}
/// @dev Internal function to determine if an address is a contract
/// @param _addr The address being queried
/// @return True if `_addr` is a contract
function isContract(address _addr) constant internal returns(bool) {
uint size;
if (_addr == 0) return false;
assembly {
size := extcodesize(_addr)
}
return size>0;
}
/// @notice The fallback function: If the contract's controller has not been
/// set to 0, then the `proxyPayment` method is called which relays the
/// ether and creates tokens as described in the token controller contract
function () payable {
if (isContract(controller)) {
if (! TokenController(controller).proxyPayment.value(msg.value)(msg.sender))
throw;
} else {
throw;
}
}
//////////
// Safety Methods
//////////
/// @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether.
function claimTokens(address _token) onlyController {
if (_token == 0x0) {
controller.transfer(this.balance);
return;
}
ERC20 token = ERC20(_token);
uint balance = token.balanceOf(this);
token.transfer(controller, balance);
ClaimedTokens(_token, controller, balance);
}
////////////////
// Events
////////////////
event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
}File 2 of 6: SwapController
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
// Token standard API
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
/// @dev The token controller contract must implement these functions
contract TokenController {
/// @notice Called when `_owner` sends ether to the MiniMe Token contract
/// @param _owner The address that sent the ether to create tokens
/// @return True if the ether is accepted, false if it throws
function proxyPayment(address _owner) payable public returns(bool);
/// @notice Notifies the controller about a token transfer allowing the
/// controller to react if desired
/// @param _from The origin of the transfer
/// @param _to The destination of the transfer
/// @param _amount The amount of the transfer
/// @return False if the controller does not authorize the transfer
function onTransfer(address _from, address _to, uint _amount) public returns(bool);
/// @notice Notifies the controller about an approval allowing the
/// controller to react if desired
/// @param _owner The address that calls `approve()`
/// @param _spender The spender in the `approve()` call
/// @param _amount The amount in the `approve()` call
/// @return False if the controller does not authorize the approval
function onApprove(address _owner, address _spender, uint _amount) public returns(bool);
}
contract Controlled {
/// @notice The address of the controller is the only address that can call
/// a function with this modifier
modifier onlyController { if (msg.sender != controller) throw; _; }
address public controller;
function Controlled() { controller = msg.sender;}
/// @notice Changes the controller of the contract
/// @param _newController The new controller of the contract
function changeController(address _newController) onlyController {
controller = _newController;
}
}
contract TokenTransferGuard {
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool);
}
contract SwapController is DSAuth, TokenController {
TokenTransferGuard[] public guards;
// Each Swap Controller has its own token, each token should set their own controller.
function SwapController(address[] _guards)
{
for (uint i=0; i<_guards.length; i++) {
addGuard(_guards[i]);
}
}
function changeController(address _token, address _newController) public auth {
Controlled(_token).changeController(_newController);
}
function proxyPayment(address _owner) payable public returns (bool)
{
return false;
}
function onTransfer(address _from, address _to, uint _amount) public returns (bool)
{
for (uint i=0; i<guards.length; i++)
{
if (!guards[i].onTokenTransfer(_from, _to, _amount))
{
return false;
}
}
return true;
}
function onApprove(address _owner, address _spender, uint _amount) public returns (bool)
{
return true;
}
function addGuard(address _guard) public auth
{
guards.push(TokenTransferGuard(_guard));
}
}File 3 of 6: AGT2ATNSwap
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
contract DSStop is DSNote, DSAuth {
bool public stopped;
modifier stoppable {
require(!stopped);
_;
}
function stop() public auth note {
stopped = true;
}
function start() public auth note {
stopped = false;
}
}
// Token standard API
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
contract TokenTransferGuard {
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool);
}
contract AGT2ATNSwap is DSStop, TokenTransferGuard {
ERC20 public AGT;
ERC20 public ATN;
uint public gasRequired;
function AGT2ATNSwap(address _agt, address _atn)
{
AGT = ERC20(_agt);
ATN = ERC20(_atn);
}
function tokenFallback(address _from, uint256 _value, bytes _data) public
{
tokenFallback(_from, _value);
}
function tokenFallback(address _from, uint256 _value) public
{
if(msg.sender == address(AGT))
{
require(ATN.transfer(_from, _value));
TokenSwap(_from, _value);
}
}
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool)
{
if (_to == address(this))
{
if (msg.gas < gasRequired) return false;
if (stopped) return false;
if (ATN.balanceOf(this) < _amount) return false;
}
return true;
}
function changeGasRequired(uint _gasRequired) public auth {
gasRequired = _gasRequired;
ChangeGasReuired(_gasRequired);
}
/// @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether.
function claimTokens(address _token) public auth {
if (_token == 0x0) {
owner.transfer(this.balance);
return;
}
ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
ClaimedTokens(_token, owner, balance);
}
event TokenSwap(address indexed _from, uint256 _value);
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
event ChangeGasReuired(uint _gasRequired);
}File 4 of 6: ATNLongTermHolding
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
// Token standard API
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
contract DSStop is DSNote, DSAuth {
bool public stopped;
modifier stoppable {
require(!stopped);
_;
}
function stop() public auth note {
stopped = true;
}
function start() public auth note {
stopped = false;
}
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
contract TokenTransferGuard {
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool);
}
contract RewardSharedPool is DSStop {
using SafeMath for uint256;
uint public maxReward = 1000000 ether;
uint public consumed = 0;
mapping(address => bool) public consumers;
modifier onlyConsumer {
require(msg.sender == owner || consumers[msg.sender]);
_;
}
function RewardSharedPool()
{
}
function consume(uint amount) onlyConsumer public returns (bool)
{
require(available(amount));
consumed = consumed.add(amount);
Consume(msg.sender, amount);
return true;
}
function available(uint amount) constant public returns (bool)
{
return consumed.add(amount) <= maxReward;
}
function changeMaxReward(uint _maxReward) auth public
{
maxReward = _maxReward;
}
function addConsumer(address consumer) public auth
{
consumers[consumer] = true;
ConsumerAddition(consumer);
}
function removeConsumer(address consumer) public auth
{
consumers[consumer] = false;
ConsumerRemoval(consumer);
}
event Consume(address indexed _sender, uint _value);
event ConsumerAddition(address indexed _consumer);
event ConsumerRemoval(address indexed _consumer);
}
contract ATNLongTermHolding is DSStop, TokenTransferGuard {
using SafeMath for uint256;
uint public constant DEPOSIT_WINDOW = 60 days;
// There are three kinds of options: 1. {105, 120 days}, 2. {110, 240 days}, 3. {115, 360 days}
uint public rate = 105;
uint public withdrawal_delay = 120 days;
uint public agtAtnReceived = 0;
uint public atnSent = 0;
uint public depositStartTime = 0;
uint public depositStopTime = 0;
RewardSharedPool public pool;
struct Record {
uint agtAtnAmount;
uint timestamp;
}
mapping (address => Record) public records;
ERC20 public AGT;
ERC20 public ATN;
uint public gasRequired;
function ATNLongTermHolding(address _agt, address _atn, address _poolAddress, uint _rate, uint _delayDays)
{
AGT = ERC20(_agt);
ATN = ERC20(_atn);
pool = RewardSharedPool(_poolAddress);
require(_rate > 100);
rate = _rate;
withdrawal_delay = _delayDays * 1 days;
}
function start() public auth {
require(depositStartTime == 0);
depositStartTime = now;
depositStopTime = now + DEPOSIT_WINDOW;
Started(depositStartTime);
}
function changeDepositStopTimeFromNow(uint _daysFromNow) public auth {
depositStopTime = now + _daysFromNow * 1 days;
}
function tokenFallback(address _from, uint256 _value, bytes _data) public
{
tokenFallback(_from, _value);
}
// TODO: To test the stoppable can work or not
function tokenFallback(address _from, uint256 _value) public stoppable
{
if (msg.sender == address(AGT) || msg.sender == address(ATN))
{
// the owner is not count in the statistics
// Only owner can use to deposit the ATN reward things.
if (_from == owner)
{
return;
}
require(now <= depositStopTime);
var record = records[_from];
record.agtAtnAmount += _value;
record.timestamp = now;
records[_from] = record;
agtAtnReceived += _value;
pool.consume( _value.mul(rate - 100 ).div(100) );
Deposit(depositId++, _from, _value);
}
}
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool)
{
if (_to == address(this) && _from != owner)
{
if (msg.gas < gasRequired) return false;
if (stopped) return false;
if (now > depositStopTime) return false;
// each address can only deposit once.
if (records[_from].timestamp > 0 ) return false;
// can not over the limit of maximum reward amount
if ( !pool.available( _amount.mul(rate - 100 ).div(100) ) ) return false;
}
return true;
}
function withdrawATN() public stoppable {
require(msg.sender != owner);
Record record = records[msg.sender];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(msg.sender);
}
function withdrawATN(address _addr) public stoppable {
require(_addr != owner);
Record record = records[_addr];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(_addr);
}
function withdrawFor(address _addr) internal {
Record record = records[_addr];
uint atnAmount = record.agtAtnAmount.mul(rate).div(100);
require(ATN.transfer(_addr, atnAmount));
atnSent += atnAmount;
delete records[_addr];
Withdrawal(
withdrawId++,
_addr,
atnAmount
);
}
function batchWithdraw(address[] _addrList) public stoppable {
for (uint i = 0; i < _addrList.length; i++) {
if (records[_addrList[i]].timestamp > 0 && now >= records[_addrList[i]].timestamp + withdrawal_delay)
{
withdrawFor(_addrList[i]);
}
}
}
function changeGasRequired(uint _gasRequired) public auth {
gasRequired = _gasRequired;
ChangeGasRequired(_gasRequired);
}
/// @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether.
function claimTokens(address _token) public auth {
if (_token == 0x0) {
owner.transfer(this.balance);
return;
}
ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
ClaimedTokens(_token, owner, balance);
}
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
/*
* EVENTS
*/
/// Emitted when program starts.
event Started(uint _time);
/// Emitted for each sucuessful deposit.
uint public depositId = 0;
event Deposit(uint _depositId, address indexed _addr, uint agtAtnAmount);
/// Emitted for each sucuessful withdrawal.
uint public withdrawId = 0;
event Withdrawal(uint _withdrawId, address indexed _addr, uint _atnAmount);
event ChangeGasRequired(uint _gasRequired);
}File 5 of 6: ATNLongTermHolding
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
// Token standard API
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
contract DSStop is DSNote, DSAuth {
bool public stopped;
modifier stoppable {
require(!stopped);
_;
}
function stop() public auth note {
stopped = true;
}
function start() public auth note {
stopped = false;
}
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
contract TokenTransferGuard {
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool);
}
contract RewardSharedPool is DSStop {
using SafeMath for uint256;
uint public maxReward = 1000000 ether;
uint public consumed = 0;
mapping(address => bool) public consumers;
modifier onlyConsumer {
require(msg.sender == owner || consumers[msg.sender]);
_;
}
function RewardSharedPool()
{
}
function consume(uint amount) onlyConsumer public returns (bool)
{
require(available(amount));
consumed = consumed.add(amount);
Consume(msg.sender, amount);
return true;
}
function available(uint amount) constant public returns (bool)
{
return consumed.add(amount) <= maxReward;
}
function changeMaxReward(uint _maxReward) auth public
{
maxReward = _maxReward;
}
function addConsumer(address consumer) public auth
{
consumers[consumer] = true;
ConsumerAddition(consumer);
}
function removeConsumer(address consumer) public auth
{
consumers[consumer] = false;
ConsumerRemoval(consumer);
}
event Consume(address indexed _sender, uint _value);
event ConsumerAddition(address indexed _consumer);
event ConsumerRemoval(address indexed _consumer);
}
contract ATNLongTermHolding is DSStop, TokenTransferGuard {
using SafeMath for uint256;
uint public constant DEPOSIT_WINDOW = 60 days;
// There are three kinds of options: 1. {105, 120 days}, 2. {110, 240 days}, 3. {115, 360 days}
uint public rate = 105;
uint public withdrawal_delay = 120 days;
uint public agtAtnReceived = 0;
uint public atnSent = 0;
uint public depositStartTime = 0;
uint public depositStopTime = 0;
RewardSharedPool public pool;
struct Record {
uint agtAtnAmount;
uint timestamp;
}
mapping (address => Record) public records;
ERC20 public AGT;
ERC20 public ATN;
uint public gasRequired;
function ATNLongTermHolding(address _agt, address _atn, address _poolAddress, uint _rate, uint _delayDays)
{
AGT = ERC20(_agt);
ATN = ERC20(_atn);
pool = RewardSharedPool(_poolAddress);
require(_rate > 100);
rate = _rate;
withdrawal_delay = _delayDays * 1 days;
}
function start() public auth {
require(depositStartTime == 0);
depositStartTime = now;
depositStopTime = now + DEPOSIT_WINDOW;
Started(depositStartTime);
}
function changeDepositStopTimeFromNow(uint _daysFromNow) public auth {
depositStopTime = now + _daysFromNow * 1 days;
}
function tokenFallback(address _from, uint256 _value, bytes _data) public
{
tokenFallback(_from, _value);
}
// TODO: To test the stoppable can work or not
function tokenFallback(address _from, uint256 _value) public stoppable
{
if (msg.sender == address(AGT) || msg.sender == address(ATN))
{
// the owner is not count in the statistics
// Only owner can use to deposit the ATN reward things.
if (_from == owner)
{
return;
}
require(now <= depositStopTime);
var record = records[_from];
record.agtAtnAmount += _value;
record.timestamp = now;
records[_from] = record;
agtAtnReceived += _value;
pool.consume( _value.mul(rate - 100 ).div(100) );
Deposit(depositId++, _from, _value);
}
}
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool)
{
if (_to == address(this) && _from != owner)
{
if (msg.gas < gasRequired) return false;
if (stopped) return false;
if (now > depositStopTime) return false;
// each address can only deposit once.
if (records[_from].timestamp > 0 ) return false;
// can not over the limit of maximum reward amount
if ( !pool.available( _amount.mul(rate - 100 ).div(100) ) ) return false;
}
return true;
}
function withdrawATN() public stoppable {
require(msg.sender != owner);
Record record = records[msg.sender];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(msg.sender);
}
function withdrawATN(address _addr) public stoppable {
require(_addr != owner);
Record record = records[_addr];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(_addr);
}
function withdrawFor(address _addr) internal {
Record record = records[_addr];
uint atnAmount = record.agtAtnAmount.mul(rate).div(100);
require(ATN.transfer(_addr, atnAmount));
atnSent += atnAmount;
delete records[_addr];
Withdrawal(
withdrawId++,
_addr,
atnAmount
);
}
function batchWithdraw(address[] _addrList) public stoppable {
for (uint i = 0; i < _addrList.length; i++) {
if (records[_addrList[i]].timestamp > 0 && now >= records[_addrList[i]].timestamp + withdrawal_delay)
{
withdrawFor(_addrList[i]);
}
}
}
function changeGasRequired(uint _gasRequired) public auth {
gasRequired = _gasRequired;
ChangeGasRequired(_gasRequired);
}
/// @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether.
function claimTokens(address _token) public auth {
if (_token == 0x0) {
owner.transfer(this.balance);
return;
}
ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
ClaimedTokens(_token, owner, balance);
}
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
/*
* EVENTS
*/
/// Emitted when program starts.
event Started(uint _time);
/// Emitted for each sucuessful deposit.
uint public depositId = 0;
event Deposit(uint _depositId, address indexed _addr, uint agtAtnAmount);
/// Emitted for each sucuessful withdrawal.
uint public withdrawId = 0;
event Withdrawal(uint _withdrawId, address indexed _addr, uint _atnAmount);
event ChangeGasRequired(uint _gasRequired);
}File 6 of 6: ATNLongTermHolding
pragma solidity ^0.4.13;
contract DSAuthority {
function canCall(
address src, address dst, bytes4 sig
) public view returns (bool);
}
contract DSAuthEvents {
event LogSetAuthority (address indexed authority);
event LogSetOwner (address indexed owner);
}
contract DSAuth is DSAuthEvents {
DSAuthority public authority;
address public owner;
function DSAuth() public {
owner = msg.sender;
LogSetOwner(msg.sender);
}
function setOwner(address owner_)
public
auth
{
owner = owner_;
LogSetOwner(owner);
}
function setAuthority(DSAuthority authority_)
public
auth
{
authority = authority_;
LogSetAuthority(authority);
}
modifier auth {
require(isAuthorized(msg.sender, msg.sig));
_;
}
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
if (src == address(this)) {
return true;
} else if (src == owner) {
return true;
} else if (authority == DSAuthority(0)) {
return false;
} else {
return authority.canCall(src, this, sig);
}
}
}
contract DSNote {
event LogNote(
bytes4 indexed sig,
address indexed guy,
bytes32 indexed foo,
bytes32 indexed bar,
uint wad,
bytes fax
) anonymous;
modifier note {
bytes32 foo;
bytes32 bar;
assembly {
foo := calldataload(4)
bar := calldataload(36)
}
LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
_;
}
}
// Token standard API
// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() public view returns (uint supply);
function balanceOf( address who ) public view returns (uint value);
function allowance( address owner, address spender ) public view returns (uint _allowance);
function transfer( address to, uint value) public returns (bool ok);
function transferFrom( address from, address to, uint value) public returns (bool ok);
function approve( address spender, uint value ) public returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
contract DSStop is DSNote, DSAuth {
bool public stopped;
modifier stoppable {
require(!stopped);
_;
}
function stop() public auth note {
stopped = true;
}
function start() public auth note {
stopped = false;
}
}
/**
* Math operations with safety checks
*/
library SafeMath {
function mul(uint a, uint b) internal returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
function max64(uint64 a, uint64 b) internal constant returns (uint64) {
return a >= b ? a : b;
}
function min64(uint64 a, uint64 b) internal constant returns (uint64) {
return a < b ? a : b;
}
function max256(uint256 a, uint256 b) internal constant returns (uint256) {
return a >= b ? a : b;
}
function min256(uint256 a, uint256 b) internal constant returns (uint256) {
return a < b ? a : b;
}
}
contract TokenTransferGuard {
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool);
}
contract RewardSharedPool is DSStop {
using SafeMath for uint256;
uint public maxReward = 1000000 ether;
uint public consumed = 0;
mapping(address => bool) public consumers;
modifier onlyConsumer {
require(msg.sender == owner || consumers[msg.sender]);
_;
}
function RewardSharedPool()
{
}
function consume(uint amount) onlyConsumer public returns (bool)
{
require(available(amount));
consumed = consumed.add(amount);
Consume(msg.sender, amount);
return true;
}
function available(uint amount) constant public returns (bool)
{
return consumed.add(amount) <= maxReward;
}
function changeMaxReward(uint _maxReward) auth public
{
maxReward = _maxReward;
}
function addConsumer(address consumer) public auth
{
consumers[consumer] = true;
ConsumerAddition(consumer);
}
function removeConsumer(address consumer) public auth
{
consumers[consumer] = false;
ConsumerRemoval(consumer);
}
event Consume(address indexed _sender, uint _value);
event ConsumerAddition(address indexed _consumer);
event ConsumerRemoval(address indexed _consumer);
}
contract ATNLongTermHolding is DSStop, TokenTransferGuard {
using SafeMath for uint256;
uint public constant DEPOSIT_WINDOW = 60 days;
// There are three kinds of options: 1. {105, 120 days}, 2. {110, 240 days}, 3. {115, 360 days}
uint public rate = 105;
uint public withdrawal_delay = 120 days;
uint public agtAtnReceived = 0;
uint public atnSent = 0;
uint public depositStartTime = 0;
uint public depositStopTime = 0;
RewardSharedPool public pool;
struct Record {
uint agtAtnAmount;
uint timestamp;
}
mapping (address => Record) public records;
ERC20 public AGT;
ERC20 public ATN;
uint public gasRequired;
function ATNLongTermHolding(address _agt, address _atn, address _poolAddress, uint _rate, uint _delayDays)
{
AGT = ERC20(_agt);
ATN = ERC20(_atn);
pool = RewardSharedPool(_poolAddress);
require(_rate > 100);
rate = _rate;
withdrawal_delay = _delayDays * 1 days;
}
function start() public auth {
require(depositStartTime == 0);
depositStartTime = now;
depositStopTime = now + DEPOSIT_WINDOW;
Started(depositStartTime);
}
function changeDepositStopTimeFromNow(uint _daysFromNow) public auth {
depositStopTime = now + _daysFromNow * 1 days;
}
function tokenFallback(address _from, uint256 _value, bytes _data) public
{
tokenFallback(_from, _value);
}
// TODO: To test the stoppable can work or not
function tokenFallback(address _from, uint256 _value) public stoppable
{
if (msg.sender == address(AGT) || msg.sender == address(ATN))
{
// the owner is not count in the statistics
// Only owner can use to deposit the ATN reward things.
if (_from == owner)
{
return;
}
require(now <= depositStopTime);
var record = records[_from];
record.agtAtnAmount += _value;
record.timestamp = now;
records[_from] = record;
agtAtnReceived += _value;
pool.consume( _value.mul(rate - 100 ).div(100) );
Deposit(depositId++, _from, _value);
}
}
function onTokenTransfer(address _from, address _to, uint _amount) public returns (bool)
{
if (_to == address(this) && _from != owner)
{
if (msg.gas < gasRequired) return false;
if (stopped) return false;
if (now > depositStopTime) return false;
// each address can only deposit once.
if (records[_from].timestamp > 0 ) return false;
// can not over the limit of maximum reward amount
if ( !pool.available( _amount.mul(rate - 100 ).div(100) ) ) return false;
}
return true;
}
function withdrawATN() public stoppable {
require(msg.sender != owner);
Record record = records[msg.sender];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(msg.sender);
}
function withdrawATN(address _addr) public stoppable {
require(_addr != owner);
Record record = records[_addr];
require(record.timestamp > 0);
require(now >= record.timestamp + withdrawal_delay);
withdrawFor(_addr);
}
function withdrawFor(address _addr) internal {
Record record = records[_addr];
uint atnAmount = record.agtAtnAmount.mul(rate).div(100);
require(ATN.transfer(_addr, atnAmount));
atnSent += atnAmount;
delete records[_addr];
Withdrawal(
withdrawId++,
_addr,
atnAmount
);
}
function batchWithdraw(address[] _addrList) public stoppable {
for (uint i = 0; i < _addrList.length; i++) {
if (records[_addrList[i]].timestamp > 0 && now >= records[_addrList[i]].timestamp + withdrawal_delay)
{
withdrawFor(_addrList[i]);
}
}
}
function changeGasRequired(uint _gasRequired) public auth {
gasRequired = _gasRequired;
ChangeGasRequired(_gasRequired);
}
/// @notice This method can be used by the controller to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0 in case you want to extract ether.
function claimTokens(address _token) public auth {
if (_token == 0x0) {
owner.transfer(this.balance);
return;
}
ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
ClaimedTokens(_token, owner, balance);
}
event ClaimedTokens(address indexed _token, address indexed _controller, uint256 _amount);
/*
* EVENTS
*/
/// Emitted when program starts.
event Started(uint _time);
/// Emitted for each sucuessful deposit.
uint public depositId = 0;
event Deposit(uint _depositId, address indexed _addr, uint agtAtnAmount);
/// Emitted for each sucuessful withdrawal.
uint public withdrawId = 0;
event Withdrawal(uint _withdrawId, address indexed _addr, uint _atnAmount);
event ChangeGasRequired(uint _gasRequired);
}