Transaction Hash:
Block:
4719507 at Dec-12-2017 11:05:05 AM +UTC
Transaction Fee:
0.000480965 ETH
$0.97
Gas Used:
96,193 Gas / 5 Gwei
Emitted Events:
| 70 |
EventsHistory.0x940c4b3549ef0aaff95807dc27f62d88ca15532d1bf535d7d63800f40395d16c( 0x940c4b3549ef0aaff95807dc27f62d88ca15532d1bf535d7d63800f40395d16c, 0x000000000000000000000000e4e7f6e7d082aeaaa1dd20907ea426a3cc70b0df, 0x00000000000000000000000021630b392896995fafd3edf9e7659126bbd04bee, 0x4343000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000004e20000, 0000000000000000000000000000000000000000000000000000000000000060, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 71 |
CryptoCarbon.Transfer( from=[Sender] 0xe4e7f6e7d082aeaaa1dd20907ea426a3cc70b0df, to=0x21630b392896995fAfD3eDf9e7659126BBD04bEE, value=81920000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x68C76947...fE4Fbd6b1 | |||||
|
0x6b7D50BB...51DD7B618
Miner
| (PandaPool) | 437.616063445108471203 Eth | 437.616544410108471203 Eth | 0.000480965 | |
| 0xd6C3FECC...a321E3131 | 3.1852532464 Eth | 3.1847504364 Eth | 0.00050281 | ||
| 0xe4E7f6e7...3cc70b0DF |
0.323580989255112063 Eth
Nonce: 13078
|
0.323602834255112063 Eth
Nonce: 13079
| 0.000021845 |
Execution Trace
CryptoCarbon.transfer( _to=0x21630b392896995fAfD3eDf9e7659126BBD04bEE, _value=81920000 ) => ( True )
-
Null: 0x000...004.CALL( )
0x68c769478002b2e2db64fe3be55c943fe4fbd6b1.64ef212e( )-
Null: 0x000...004.CALL( )
EventsHistory.515c1457( )
MultiAssetEmitter.emitTransfer( _from=0xe4E7f6e7d082aeaAa1Dd20907Ea426A3cc70b0DF, _to=0x21630b392896995fAfD3eDf9e7659126BBD04bEE, _symbol=4343000000000000000000000000000000000000000000000000000000000000, _value=81920000, _reference= )-
EventsHistory.versions( 0x68C769478002B2E2Db64fE3Be55C943fE4Fbd6b1 ) => ( 1 )
-
Null: 0x000...004.CALL( )
-
StackDepthLib.checkDepth( self=0x606dDac6F2928369e8515340f8dE97Fe2d166777, n=1 ) => ( True )-
StackDepthLib.__dig( n=0 )
-
-
CryptoCarbon.emitTransfer( _from=0xe4E7f6e7d082aeaAa1Dd20907Ea426A3cc70b0DF, _to=0x21630b392896995fAfD3eDf9e7659126BBD04bEE, _value=81920000 )
-
0xd6c3fecce74e5fb3a9bcc6bbaaebf80a321e3131.f3fef3a3( )
- ETH 0.00050281
0xe4e7f6e7d082aeaaa1dd20907ea426a3cc70b0df.CALL( )
- ETH 0.00050281
File 1 of 4: CryptoCarbon
File 2 of 4: EventsHistory
File 3 of 4: MultiAssetEmitter
File 4 of 4: StackDepthLib
contract MultiAsset {
function isCreated(bytes32 _symbol) constant returns(bool);
function owner(bytes32 _symbol) constant returns(address);
function totalSupply(bytes32 _symbol) constant returns(uint);
function balanceOf(address _holder, bytes32 _symbol) constant returns(uint);
function transfer(address _to, uint _value, bytes32 _symbol) returns(bool);
function proxyTransferWithReference(address _to, uint _value, bytes32 _symbol, string _reference) returns(bool);
function proxyTransferToICAPWithReference(bytes32 _icap, uint _value, string _reference) returns(bool);
function proxyApprove(address _spender, uint _value, bytes32 _symbol) returns(bool);
function allowance(address _from, address _spender, bytes32 _symbol) constant returns(uint);
function transferFromWithReference(address _from, address _to, uint _value, bytes32 _symbol, string _reference) returns(bool);
function transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) returns(bool);
function proxyTransferFromWithReference(address _from, address _to, uint _value, bytes32 _symbol, string _reference) returns(bool);
function proxyTransferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) returns(bool);
function proxySetCosignerAddress(address _address, bytes32 _symbol) returns(bool);
}
contract Ambi {
function getNodeAddress(bytes32 _name) constant returns (address);
function addNode(bytes32 _name, address _addr) external returns (bool);
function hasRelation(bytes32 _from, bytes32 _role, address _to) constant returns (bool);
}
contract EtherTreasuryInterface {
function withdraw(address _to, uint _value) returns(bool);
}
contract Safe {
// Should always be placed as first modifier!
modifier noValue {
if (msg.value > 0) {
// Internal Out Of Gas/Throw: revert this transaction too;
// Call Stack Depth Limit reached: revert this transaction too;
// Recursive Call: safe, no any changes applied yet, we are inside of modifier.
_safeSend(msg.sender, msg.value);
}
_
}
modifier onlyHuman {
if (_isHuman()) {
_
}
}
modifier noCallback {
if (!isCall) {
_
}
}
modifier immutable(address _address) {
if (_address == 0) {
_
}
}
address stackDepthLib;
function setupStackDepthLib(address _stackDepthLib) immutable(address(stackDepthLib)) returns(bool) {
stackDepthLib = _stackDepthLib;
return true;
}
modifier requireStackDepth(uint16 _depth) {
if (stackDepthLib == 0x0) {
throw;
}
if (_depth > 1023) {
throw;
}
if (!stackDepthLib.delegatecall(0x32921690, stackDepthLib, _depth)) {
throw;
}
_
}
// Must not be used inside the functions that have noValue() modifier!
function _safeFalse() internal noValue() returns(bool) {
return false;
}
function _safeSend(address _to, uint _value) internal {
if (!_unsafeSend(_to, _value)) {
throw;
}
}
function _unsafeSend(address _to, uint _value) internal returns(bool) {
return _to.call.value(_value)();
}
function _isContract() constant internal returns(bool) {
return msg.sender != tx.origin;
}
function _isHuman() constant internal returns(bool) {
return !_isContract();
}
bool private isCall = false;
function _setupNoCallback() internal {
isCall = true;
}
function _finishNoCallback() internal {
isCall = false;
}
}
contract Asset is Safe {
event Transfer(address indexed from, address indexed to, uint value);
event Approve(address indexed from, address indexed spender, uint value);
MultiAsset public multiAsset;
bytes32 public symbol;
function init(address _multiAsset, bytes32 _symbol) noValue() immutable(address(multiAsset)) returns(bool) {
MultiAsset ma = MultiAsset(_multiAsset);
if (!ma.isCreated(_symbol)) {
return false;
}
multiAsset = ma;
symbol = _symbol;
return true;
}
modifier onlyMultiAsset() {
if (msg.sender == address(multiAsset)) {
_
}
}
function totalSupply() constant returns(uint) {
return multiAsset.totalSupply(symbol);
}
function balanceOf(address _owner) constant returns(uint) {
return multiAsset.balanceOf(_owner, symbol);
}
function allowance(address _from, address _spender) constant returns(uint) {
return multiAsset.allowance(_from, _spender, symbol);
}
function transfer(address _to, uint _value) returns(bool) {
return __transferWithReference(_to, _value, "");
}
function transferWithReference(address _to, uint _value, string _reference) returns(bool) {
return __transferWithReference(_to, _value, _reference);
}
function __transferWithReference(address _to, uint _value, string _reference) private noValue() returns(bool) {
return _isHuman() ?
multiAsset.proxyTransferWithReference(_to, _value, symbol, _reference) :
multiAsset.transferFromWithReference(msg.sender, _to, _value, symbol, _reference);
}
function transferToICAP(bytes32 _icap, uint _value) returns(bool) {
return __transferToICAPWithReference(_icap, _value, "");
}
function transferToICAPWithReference(bytes32 _icap, uint _value, string _reference) returns(bool) {
return __transferToICAPWithReference(_icap, _value, _reference);
}
function __transferToICAPWithReference(bytes32 _icap, uint _value, string _reference) private noValue() returns(bool) {
return _isHuman() ?
multiAsset.proxyTransferToICAPWithReference(_icap, _value, _reference) :
multiAsset.transferFromToICAPWithReference(msg.sender, _icap, _value, _reference);
}
function transferFrom(address _from, address _to, uint _value) returns(bool) {
return __transferFromWithReference(_from, _to, _value, "");
}
function transferFromWithReference(address _from, address _to, uint _value, string _reference) returns(bool) {
return __transferFromWithReference(_from, _to, _value, _reference);
}
function __transferFromWithReference(address _from, address _to, uint _value, string _reference) private noValue() onlyHuman() returns(bool) {
return multiAsset.proxyTransferFromWithReference(_from, _to, _value, symbol, _reference);
}
function transferFromToICAP(address _from, bytes32 _icap, uint _value) returns(bool) {
return __transferFromToICAPWithReference(_from, _icap, _value, "");
}
function transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) returns(bool) {
return __transferFromToICAPWithReference(_from, _icap, _value, _reference);
}
function __transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) private noValue() onlyHuman() returns(bool) {
return multiAsset.proxyTransferFromToICAPWithReference(_from, _icap, _value, _reference);
}
function approve(address _spender, uint _value) noValue() onlyHuman() returns(bool) {
return multiAsset.proxyApprove(_spender, _value, symbol);
}
function setCosignerAddress(address _cosigner) noValue() onlyHuman() returns(bool) {
return multiAsset.proxySetCosignerAddress(_cosigner, symbol);
}
function emitTransfer(address _from, address _to, uint _value) onlyMultiAsset() {
Transfer(_from, _to, _value);
}
function emitApprove(address _from, address _spender, uint _value) onlyMultiAsset() {
Approve(_from, _spender, _value);
}
function sendToOwner() noValue() returns(bool) {
address owner = multiAsset.owner(symbol);
uint balance = this.balance;
bool success = true;
if (balance > 0) {
success = _unsafeSend(owner, balance);
}
return multiAsset.transfer(owner, balanceOf(owner), symbol) && success;
}
}
contract AmbiEnabled {
Ambi public ambiC;
bool public isImmortal;
bytes32 public name;
modifier checkAccess(bytes32 _role) {
if(address(ambiC) != 0x0 && ambiC.hasRelation(name, _role, msg.sender)){
_
}
}
function getAddress(bytes32 _name) constant returns (address) {
return ambiC.getNodeAddress(_name);
}
function setAmbiAddress(address _ambi, bytes32 _name) returns (bool){
if(address(ambiC) != 0x0){
return false;
}
Ambi ambiContract = Ambi(_ambi);
if(ambiContract.getNodeAddress(_name)!=address(this)) {
if (!ambiContract.addNode(_name, address(this))){
return false;
}
}
name = _name;
ambiC = ambiContract;
return true;
}
function immortality() checkAccess("owner") returns(bool) {
isImmortal = true;
return true;
}
function remove() checkAccess("owner") returns(bool) {
if (isImmortal) {
return false;
}
selfdestruct(msg.sender);
return true;
}
}
contract CryptoCarbon is Asset, AmbiEnabled {
uint public txGasPriceLimit = 21000000000;
uint public refundGas = 40000;
uint public transferCallGas = 21000;
uint public transferWithReferenceCallGas = 21000;
uint public transferFromCallGas = 21000;
uint public transferFromWithReferenceCallGas = 21000;
uint public transferToICAPCallGas = 21000;
uint public transferToICAPWithReferenceCallGas = 21000;
uint public transferFromToICAPCallGas = 21000;
uint public transferFromToICAPWithReferenceCallGas = 21000;
uint public approveCallGas = 21000;
uint public forwardCallGas = 21000;
uint public setCosignerCallGas = 21000;
uint public absMinFee;
uint public feePercent; // set up in 1/100 of percent, 10 is 0.1%
uint public absMaxFee;
EtherTreasuryInterface public treasury;
address public feeAddress;
bool private __isAllowed;
mapping(bytes32 => address) public allowedForwards;
function setFeeStructure(uint _absMinFee, uint _feePercent, uint _absMaxFee) noValue() checkAccess("cron") returns (bool) {
if(_feePercent > 10000 || _absMaxFee < _absMinFee) {
return false;
}
absMinFee = _absMinFee;
feePercent = _feePercent;
absMaxFee = _absMaxFee;
return true;
}
function setupFee(address _feeAddress) noValue() checkAccess("admin") returns(bool) {
feeAddress = _feeAddress;
return true;
}
function updateRefundGas() noValue() checkAccess("setup") returns(uint) {
uint startGas = msg.gas;
// just to simulate calculations
uint refund = (startGas - msg.gas + refundGas) * tx.gasprice;
if (tx.gasprice > txGasPriceLimit) {
return 0;
}
// end
if (!_refund(5000000000000000)) {
return 0;
}
refundGas = startGas - msg.gas;
return refundGas;
}
function setOperationsCallGas(
uint _transfer,
uint _transferFrom,
uint _transferToICAP,
uint _transferFromToICAP,
uint _transferWithReference,
uint _transferFromWithReference,
uint _transferToICAPWithReference,
uint _transferFromToICAPWithReference,
uint _approve,
uint _forward,
uint _setCosigner
)
noValue()
checkAccess("setup")
returns(bool)
{
transferCallGas = _transfer;
transferFromCallGas = _transferFrom;
transferToICAPCallGas = _transferToICAP;
transferFromToICAPCallGas = _transferFromToICAP;
transferWithReferenceCallGas = _transferWithReference;
transferFromWithReferenceCallGas = _transferFromWithReference;
transferToICAPWithReferenceCallGas = _transferToICAPWithReference;
transferFromToICAPWithReferenceCallGas = _transferFromToICAPWithReference;
approveCallGas = _approve;
forwardCallGas = _forward;
setCosignerCallGas = _setCosigner;
return true;
}
function setupTreasury(address _treasury, uint _txGasPriceLimit) checkAccess("admin") returns(bool) {
if (_txGasPriceLimit == 0) {
return _safeFalse();
}
treasury = EtherTreasuryInterface(_treasury);
txGasPriceLimit = _txGasPriceLimit;
if (msg.value > 0) {
_safeSend(_treasury, msg.value);
}
return true;
}
function setForward(bytes4 _msgSig, address _forward) noValue() checkAccess("admin") returns(bool) {
allowedForwards[sha3(_msgSig)] = _forward;
return true;
}
function _stringGas(string _string) constant internal returns(uint) {
return bytes(_string).length * 75; // ~75 gas per byte, empirical shown 68-72.
}
function _transferFee(address _feeFrom, uint _value, string _reference) internal returns(bool) {
if (feeAddress == 0x0 || feeAddress == _feeFrom || _value == 0) {
return true;
}
return multiAsset.transferFromWithReference(_feeFrom, feeAddress, _value, symbol, _reference);
}
function _returnFee(address _to, uint _value) internal returns(bool, bool) {
if (feeAddress == 0x0 || feeAddress == _to || _value == 0) {
return (false, true);
}
if (!multiAsset.transferFromWithReference(feeAddress, _to, _value, symbol, "Fee return")) {
throw;
}
return (false, true);
}
function _applyRefund(uint _startGas) internal returns(bool) {
uint refund = (_startGas - msg.gas + refundGas) * tx.gasprice;
return _refund(refund);
}
function _refund(uint _value) internal returns(bool) {
if (tx.gasprice > txGasPriceLimit) {
return false;
}
return treasury.withdraw(tx.origin, _value);
}
function _allow() internal {
__isAllowed = true;
}
function _disallow() internal {
__isAllowed = false;
}
function calculateFee(uint _value) constant returns(uint) {
uint fee = (_value * feePercent) / 10000;
if (fee < absMinFee) {
return absMinFee;
}
if (fee > absMaxFee) {
return absMaxFee;
}
return fee;
}
function calculateFeeDynamic(uint _value, uint _additionalGas) constant returns(uint) {
uint fee = calculateFee(_value);
if (_additionalGas <= 7500) {
return fee;
}
// Assuming that absMinFee covers at least 100000 gas refund, let's add another absMinFee
// for every other 100000 additional gas.
uint additionalFee = ((_additionalGas / 100000) + 1) * absMinFee;
return fee + additionalFee;
}
function takeFee(address _feeFrom, uint _value, string _reference) noValue() checkAccess("fee") returns(bool) {
return _transferFee(_feeFrom, _value, _reference);
}
function _transfer(address _to, uint _value) internal returns(bool, bool) {
uint startGas = msg.gas + transferCallGas;
uint fee = calculateFee(_value);
if (!_transferFee(msg.sender, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transfer(_to, _value);
_disallow();
if (!success) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas));
}
function _transferFrom(address _from, address _to, uint _value) internal returns(bool, bool) {
uint startGas = msg.gas + transferFromCallGas;
_allow();
uint fee = calculateFee(_value);
if (!_transferFee(_from, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferFrom(_from, _to, _value);
_disallow();
if (!success) {
return _returnFee(_from, fee);
}
return (true, _applyRefund(startGas));
}
function _transferToICAP(bytes32 _icap, uint _value) internal returns(bool, bool) {
uint startGas = msg.gas + transferToICAPCallGas;
uint fee = calculateFee(_value);
if (!_transferFee(msg.sender, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferToICAP(_icap, _value);
_disallow();
if (!success) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas));
}
function _transferFromToICAP(address _from, bytes32 _icap, uint _value) internal returns(bool, bool) {
uint startGas = msg.gas + transferFromToICAPCallGas;
uint fee = calculateFee(_value);
if (!_transferFee(_from, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferFromToICAP(_from, _icap, _value);
_disallow();
if (!success) {
return _returnFee(_from, fee);
}
return (true, _applyRefund(startGas));
}
function _transferWithReference(address _to, uint _value, string _reference) internal returns(bool, bool) {
uint startGas = msg.gas + transferWithReferenceCallGas;
uint additionalGas = _stringGas(_reference);
uint fee = calculateFeeDynamic(_value, additionalGas);
if (!_transferFee(msg.sender, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferWithReference(_to, _value, _reference);
_disallow();
if (!success) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas + additionalGas));
}
function _transferFromWithReference(address _from, address _to, uint _value, string _reference) internal returns(bool, bool) {
uint startGas = msg.gas + transferFromWithReferenceCallGas;
uint additionalGas = _stringGas(_reference);
uint fee = calculateFeeDynamic(_value, additionalGas);
if (!_transferFee(_from, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferFromWithReference(_from, _to, _value, _reference);
_disallow();
if (!success) {
return _returnFee(_from, fee);
}
return (true, _applyRefund(startGas + additionalGas));
}
function _transferToICAPWithReference(bytes32 _icap, uint _value, string _reference) internal returns(bool, bool) {
uint startGas = msg.gas + transferToICAPWithReferenceCallGas;
uint additionalGas = _stringGas(_reference);
uint fee = calculateFeeDynamic(_value, additionalGas);
if (!_transferFee(msg.sender, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferToICAPWithReference(_icap, _value, _reference);
_disallow();
if (!success) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas + additionalGas));
}
function _transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) internal returns(bool, bool) {
uint startGas = msg.gas + transferFromToICAPWithReferenceCallGas;
uint additionalGas = _stringGas(_reference);
uint fee = calculateFeeDynamic(_value, additionalGas);
if (!_transferFee(_from, fee, "Transfer fee")) {
return (false, false);
}
_allow();
bool success = super.transferFromToICAPWithReference(_from, _icap, _value, _reference);
_disallow();
if (!success) {
return _returnFee(_from, fee);
}
return (true, _applyRefund(startGas + additionalGas));
}
function _approve(address _spender, uint _value) internal returns(bool, bool) {
uint startGas = msg.gas + approveCallGas;
// Don't take fee when enabling fee taking.
// Don't refund either.
if (_spender == address(this)) {
return (super.approve(_spender, _value), false);
}
uint fee = calculateFee(0);
if (!_transferFee(msg.sender, fee, "Approve fee")) {
return (false, false);
}
_allow();
bool success = super.approve(_spender, _value);
_disallow();
if (!success) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas));
}
function _setCosignerAddress(address _cosigner) internal returns(bool, bool) {
uint startGas = msg.gas + setCosignerCallGas;
uint fee = calculateFee(0);
if (!_transferFee(msg.sender, fee, "Cosigner fee")) {
return (false, false);
}
if (!super.setCosignerAddress(_cosigner)) {
return _returnFee(msg.sender, fee);
}
return (true, _applyRefund(startGas));
}
function transfer(address _to, uint _value) returns(bool) {
bool success;
(success,) = _transfer(_to, _value);
return success;
}
function transferFrom(address _from, address _to, uint _value) returns(bool) {
bool success;
(success,) = _transferFrom(_from, _to, _value);
return success;
}
function transferToICAP(bytes32 _icap, uint _value) returns(bool) {
bool success;
(success,) = _transferToICAP(_icap, _value);
return success;
}
function transferFromToICAP(address _from, bytes32 _icap, uint _value) returns(bool) {
bool success;
(success,) = _transferFromToICAP(_from, _icap, _value);
return success;
}
function transferWithReference(address _to, uint _value, string _reference) returns(bool) {
bool success;
(success,) = _transferWithReference(_to, _value, _reference);
return success;
}
function transferFromWithReference(address _from, address _to, uint _value, string _reference) returns(bool) {
bool success;
(success,) = _transferFromWithReference(_from, _to, _value, _reference);
return success;
}
function transferToICAPWithReference(bytes32 _icap, uint _value, string _reference) returns(bool) {
bool success;
(success,) = _transferToICAPWithReference(_icap, _value, _reference);
return success;
}
function transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) returns(bool) {
bool success;
(success,) = _transferFromToICAPWithReference(_from, _icap, _value, _reference);
return success;
}
function approve(address _spender, uint _value) returns(bool) {
bool success;
(success,) = _approve(_spender, _value);
return success;
}
function setCosignerAddress(address _cosigner) returns(bool) {
bool success;
(success,) = _setCosignerAddress(_cosigner);
return success;
}
function checkTransfer(address _to, uint _value) constant returns(bool, bool) {
return _transfer(_to, _value);
}
function checkTransferFrom(address _from, address _to, uint _value) constant returns(bool, bool) {
return _transferFrom(_from, _to, _value);
}
function checkTransferToICAP(bytes32 _icap, uint _value) constant returns(bool, bool) {
return _transferToICAP(_icap, _value);
}
function checkTransferFromToICAP(address _from, bytes32 _icap, uint _value) constant returns(bool, bool) {
return _transferFromToICAP(_from, _icap, _value);
}
function checkTransferWithReference(address _to, uint _value, string _reference) constant returns(bool, bool) {
return _transferWithReference(_to, _value, _reference);
}
function checkTransferFromWithReference(address _from, address _to, uint _value, string _reference) constant returns(bool, bool) {
return _transferFromWithReference(_from, _to, _value, _reference);
}
function checkTransferToICAPWithReference(bytes32 _icap, uint _value, string _reference) constant returns(bool, bool) {
return _transferToICAPWithReference(_icap, _value, _reference);
}
function checkTransferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference) constant returns(bool, bool) {
return _transferFromToICAPWithReference(_from, _icap, _value, _reference);
}
function checkApprove(address _spender, uint _value) constant returns(bool, bool) {
return _approve(_spender, _value);
}
function checkSetCosignerAddress(address _cosigner) constant returns(bool, bool) {
return _setCosignerAddress(_cosigner);
}
function checkForward(bytes _data) constant returns(bool, bool) {
return _forward(allowedForwards[sha3(_data[0], _data[1], _data[2], _data[3])], _data);
}
function _forward(address _to, bytes _data) internal returns(bool, bool) {
uint startGas = msg.gas + forwardCallGas;
uint additionalGas = (_data.length * 50); // 50 gas per byte;
if (_to == 0x0) {
return (false, _safeFalse());
}
uint fee = calculateFeeDynamic(0, additionalGas);
if (!_transferFee(msg.sender, fee, "Forward fee")) {
return (false, false);
}
if (!_to.call.value(msg.value)(_data)) {
_returnFee(msg.sender, fee);
return (false, _safeFalse());
}
return (true, _applyRefund(startGas + additionalGas));
}
function () returns(bool) {
bool success;
(success,) = _forward(allowedForwards[sha3(msg.sig)], msg.data);
return success;
}
function emitTransfer(address _from, address _to, uint _value) onlyMultiAsset() {
Transfer(_from, _to, _value);
if (__isAllowed) {
return;
}
if (feeAddress == 0x0 || _to == feeAddress || _from == feeAddress) {
return;
}
if (_transferFee(_from, calculateFee(_value), "Transfer fee")) {
return;
}
throw;
}
function emitApprove(address _from, address _spender, uint _value) onlyMultiAsset() {
Approve(_from, _spender, _value);
if (__isAllowed) {
return;
}
if (feeAddress == 0x0 || _spender == address(this)) {
return;
}
if (_transferFee(_from, calculateFee(0), "Approve fee")) {
return;
}
throw;
}
}File 2 of 4: EventsHistory
// This software is a subject to Ambisafe License Agreement.
// No use or distribution is allowed without written permission from Ambisafe.
// https://ambisafe.com/terms.pdf
contract Ambi {
function getNodeAddress(bytes32 _nodeName) constant returns(address);
function hasRelation(bytes32 _nodeName, bytes32 _relation, address _to) constant returns(bool);
function addNode(bytes32 _nodeName, address _nodeAddress) constant returns(bool);
}
contract AmbiEnabled {
Ambi public ambiC;
bool public isImmortal;
bytes32 public name;
modifier checkAccess(bytes32 _role) {
if(address(ambiC) != 0x0 && ambiC.hasRelation(name, _role, msg.sender)){
_
}
}
function getAddress(bytes32 _name) constant returns (address) {
return ambiC.getNodeAddress(_name);
}
function setAmbiAddress(address _ambi, bytes32 _name) returns (bool){
if(address(ambiC) != 0x0){
return false;
}
Ambi ambiContract = Ambi(_ambi);
if(ambiContract.getNodeAddress(_name)!=address(this)) {
if (!ambiContract.addNode(_name, address(this))){
return false;
}
}
name = _name;
ambiC = ambiContract;
return true;
}
function immortality() checkAccess("owner") returns(bool) {
isImmortal = true;
return true;
}
function remove() checkAccess("owner") returns(bool) {
if (isImmortal) {
return false;
}
selfdestruct(msg.sender);
return true;
}
}
library StackDepthLib {
// This will probably work with a value of 390 but no need to cut it
// that close in the case that the optimizer changes slightly or
// something causing that number to rise slightly.
uint constant GAS_PER_DEPTH = 400;
function checkDepth(address self, uint n) constant returns(bool) {
if (n == 0) return true;
return self.call.gas(GAS_PER_DEPTH * n)(0x21835af6, n - 1);
}
function __dig(uint n) constant {
if (n == 0) return;
if (!address(this).delegatecall(0x21835af6, n - 1)) throw;
}
}
contract Safe {
// Should always be placed as first modifier!
modifier noValue {
if (msg.value > 0) {
// Internal Out Of Gas/Throw: revert this transaction too;
// Call Stack Depth Limit reached: revert this transaction too;
// Recursive Call: safe, no any changes applied yet, we are inside of modifier.
_safeSend(msg.sender, msg.value);
}
_
}
modifier onlyHuman {
if (_isHuman()) {
_
}
}
modifier noCallback {
if (!isCall) {
_
}
}
modifier immutable(address _address) {
if (_address == 0) {
_
}
}
address stackDepthLib;
function setupStackDepthLib(address _stackDepthLib) immutable(address(stackDepthLib)) returns(bool) {
stackDepthLib = _stackDepthLib;
return true;
}
modifier requireStackDepth(uint16 _depth) {
if (stackDepthLib == 0x0) {
throw;
}
if (_depth > 1023) {
throw;
}
if (!stackDepthLib.delegatecall(0x32921690, stackDepthLib, _depth)) {
throw;
}
_
}
// Must not be used inside the functions that have noValue() modifier!
function _safeFalse() internal noValue() returns(bool) {
return false;
}
function _safeSend(address _to, uint _value) internal {
if (!_unsafeSend(_to, _value)) {
throw;
}
}
function _unsafeSend(address _to, uint _value) internal returns(bool) {
return _to.call.value(_value)();
}
function _isContract() constant internal returns(bool) {
return msg.sender != tx.origin;
}
function _isHuman() constant internal returns(bool) {
return !_isContract();
}
bool private isCall = false;
function _setupNoCallback() internal {
isCall = true;
}
function _finishNoCallback() internal {
isCall = false;
}
}
/**
* @title Events History universal contract.
*
* Contract serves as an Events storage and version history for a particular contract type.
* Events appear on this contract address but their definitions provided by other contracts/libraries.
* Version info is provided for historical and informational purposes.
*
* Note: all the non constant functions return false instead of throwing in case if state change
* didn't happen yet.
*/
contract EventsHistory is AmbiEnabled, Safe {
// Event emitter signature to address with Event definiton mapping.
mapping(bytes4 => address) public emitters;
// Calling contract address to version mapping.
mapping(address => uint) public versions;
// Version to info mapping.
mapping(uint => VersionInfo) public versionInfo;
// Latest verion number.
uint public latestVersion;
struct VersionInfo {
uint block; // Block number in which version has been introduced.
address by; // Contract owner address who added version.
address caller; // Address of this version calling contract.
string name; // Version name, informative.
string changelog; // Version changelog, informative.
}
/**
* Assign emitter address to a specified emit function signature.
*
* Can be set only once for each signature, and only by contract owner.
* Caller contract should be sure that emitter for a particular signature will never change.
*
* @param _eventSignature signature of the event emitting function.
* @param _emitter address with Event definition.
*
* @return success.
*/
function addEmitter(bytes4 _eventSignature, address _emitter) noValue() checkAccess("admin") returns(bool) {
if (emitters[_eventSignature] != 0x0) {
return false;
}
emitters[_eventSignature] = _emitter;
return true;
}
/**
* Introduce new caller contract version specifing version information.
*
* Can be set only once for each caller, and only by contract owner.
* Name and changelog should not be empty.
*
* @param _caller address of the new caller.
* @param _name version name.
* @param _changelog version changelog.
*
* @return success.
*/
function addVersion(address _caller, string _name, string _changelog) noValue() checkAccess("admin") returns(bool) {
if (versions[_caller] != 0) {
return false;
}
if (bytes(_name).length == 0) {
return false;
}
if (bytes(_changelog).length == 0) {
return false;
}
uint version = ++latestVersion;
versions[_caller] = version;
versionInfo[version] = VersionInfo(block.number, msg.sender, _caller, _name, _changelog);
return true;
}
/**
* Event emitting fallback.
*
* Can be and only called caller with assigned version.
* Resolves msg.sig to an emitter address, and calls it to emit an event.
*
* Throws if emit function signature is not registered, or call failed.
*/
function () noValue() {
if (versions[msg.sender] == 0) {
return;
}
// Internal Out Of Gas/Throw: revert this transaction too;
// Call Stack Depth Limit reached: revert this transaction too;
// Recursive Call: safe, all changes already made.
if (!emitters[msg.sig].delegatecall(msg.data)) {
throw;
}
}
}File 3 of 4: MultiAssetEmitter
// This software is a subject to Ambisafe License Agreement.
// No use or distribution is allowed without written permission from Ambisafe.
// https://ambisafe.com/terms.pdf
contract EventsHistory {
function versions(address) constant returns(uint);
}
/**
* @title MultiAsset Emitter.
*
* Contains all the original event emitting function definitions and events.
* In case of new events needed later, additional emitters can be developed.
* All the functions is meant to be called using delegatecall.
*/
library MultiAssetEmitter {
event Transfer(address indexed from, address indexed to, bytes32 indexed symbol, uint value, string reference, uint version);
event Issue(bytes32 indexed symbol, uint value, address by, uint version);
event Revoke(bytes32 indexed symbol, uint value, address by, uint version);
event OwnershipChange(address indexed from, address indexed to, bytes32 indexed symbol, uint version);
event Approve(address indexed from, address indexed spender, bytes32 indexed symbol, uint value, uint version);
event Recovery(address indexed from, address indexed to, address by, uint version);
event TransferToICAP(address indexed from, address indexed to, bytes32 indexed icap, uint value, string reference, uint version);
event Error(bytes32 message, uint version);
function emitTransfer(address _from, address _to, bytes32 _symbol, uint _value, string _reference) {
Transfer(_from, _to, _symbol, _value, _reference, _getVersion());
}
function emitIssue(bytes32 _symbol, uint _value, address _by) {
Issue(_symbol, _value, _by, _getVersion());
}
function emitRevoke(bytes32 _symbol, uint _value, address _by) {
Revoke(_symbol, _value, _by, _getVersion());
}
function emitOwnershipChange(address _from, address _to, bytes32 _symbol) {
OwnershipChange(_from, _to, _symbol, _getVersion());
}
function emitApprove(address _from, address _spender, bytes32 _symbol, uint _value) {
Approve(_from, _spender, _symbol, _value, _getVersion());
}
function emitRecovery(address _from, address _to, address _by) {
Recovery(_from, _to, _by, _getVersion());
}
function emitTransferToICAP(address _from, address _to, bytes32 _icap, uint _value, string _reference) {
TransferToICAP(_from, _to, _icap, _value, _reference, _getVersion());
}
function emitError(bytes32 _message) {
Error(_message, _getVersion());
}
/**
* Get version number of the caller.
*
* Assuming that the call is made by EventsHistory using delegate call,
* context was not changed, so the caller is the address that called
* EventsHistory.
*
* @return current context caller version number.
*/
function _getVersion() constant internal returns(uint) {
return EventsHistory(address(this)).versions(msg.sender);
}
}File 4 of 4: StackDepthLib
// https://github.com/pipermerriam/ethereum-stack-depth-lib
library StackDepthLib {
// This will probably work with a value of 390 but no need to cut it
// that close in the case that the optimizer changes slightly or
// something causing that number to rise slightly.
uint constant GAS_PER_DEPTH = 400;
function checkDepth(address self, uint n) constant returns(bool) {
if (n == 0) return true;
return self.call.gas(GAS_PER_DEPTH * n)(0x21835af6, n - 1);
}
function __dig(uint n) constant {
if (n == 0) return;
if (!address(this).delegatecall(0x21835af6, n - 1)) throw;
}
}