// This software is a subject to Ambisafe License Agreement.
// No use or distribution is allowed without written permission from Ambisafe.
// https://www.ambisafe.co/terms-of-use/
pragma solidity 0.4.15;
contract Ambi2 {
function claimFor(address _address, address _owner) returns(bool);
function hasRole(address _from, bytes32 _role, address _to) constant returns(bool);
function isOwner(address _node, address _owner) constant returns(bool);
}
contract Ambi2Enabled {
Ambi2 ambi2;
modifier onlyRole(bytes32 _role) {
if (address(ambi2) != 0x0 && ambi2.hasRole(this, _role, msg.sender)) {
_;
}
}
// Perform only after claiming the node, or claim in the same tx.
function setupAmbi2(Ambi2 _ambi2) returns(bool) {
if (address(ambi2) != 0x0) {
return false;
}
ambi2 = _ambi2;
return true;
}
}
contract Ambi2EnabledFull is Ambi2Enabled {
// Setup and claim atomically.
function setupAmbi2(Ambi2 _ambi2) returns(bool) {
if (address(ambi2) != 0x0) {
return false;
}
if (!_ambi2.claimFor(this, msg.sender) && !_ambi2.isOwner(this, msg.sender)) {
return false;
}
ambi2 = _ambi2;
return true;
}
}
contract ReturnData {
function _returnReturnData(bool _success) internal {
assembly {
let returndatastart := msize()
mstore(0x40, add(returndatastart, returndatasize))
returndatacopy(returndatastart, 0, returndatasize)
switch _success case 0 { revert(returndatastart, returndatasize) } default { return(returndatastart, returndatasize) }
}
}
function _assemblyCall(address _destination, uint _value, bytes _data) internal returns(bool success) {
assembly {
success := call(div(mul(gas, 63), 64), _destination, _value, add(_data, 32), mload(_data), 0, 0)
}
}
}
contract Bytes32 {
function _bytes32(string _input) internal constant returns(bytes32 result) {
assembly {
result := mload(add(_input, 32))
}
}
}
contract AssetInterface {
function _performTransferWithReference(address _to, uint _value, string _reference, address _sender) returns(bool);
function _performTransferToICAPWithReference(bytes32 _icap, uint _value, string _reference, address _sender) returns(bool);
function _performApprove(address _spender, uint _value, address _sender) returns(bool);
function _performTransferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender) returns(bool);
function _performTransferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference, address _sender) returns(bool);
function _performGeneric(bytes, address) payable {
revert();
}
}
/**
* @title EToken2 Asset implementation contract.
*
* Basic asset implementation contract, without any additional logic.
* Every other asset implementation contracts should derive from this one.
* Receives calls from the proxy, and calls back immediatly without arguments modification.
*
* Note: all the non constant functions return false instead of throwing in case if state change
* didn't happen yet.
*/
contract Asset is AssetInterface, Bytes32, ReturnData {
// Assigned asset proxy contract, immutable.
AssetProxy public proxy;
/**
* Only assigned proxy is allowed to call.
*/
modifier onlyProxy() {
if (proxy == msg.sender) {
_;
}
}
/**
* Sets asset proxy address.
*
* Can be set only once.
*
* @param _proxy asset proxy contract address.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function init(AssetProxy _proxy) returns(bool) {
if (address(proxy) != 0x0) {
return false;
}
proxy = _proxy;
return true;
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function _performTransferWithReference(address _to, uint _value, string _reference, address _sender) onlyProxy() returns(bool) {
if (isICAP(_to)) {
return _transferToICAPWithReference(bytes32(_to) << 96, _value, _reference, _sender);
}
return _transferWithReference(_to, _value, _reference, _sender);
}
/**
* Calls back without modifications.
*
* @return success.
* @dev function is virtual, and meant to be overridden.
*/
function _transferWithReference(address _to, uint _value, string _reference, address _sender) internal returns(bool) {
return proxy._forwardTransferFromWithReference(_sender, _to, _value, _reference, _sender);
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function _performTransferToICAPWithReference(bytes32 _icap, uint _value, string _reference, address _sender) onlyProxy() returns(bool) {
return _transferToICAPWithReference(_icap, _value, _reference, _sender);
}
/**
* Calls back without modifications.
*
* @return success.
* @dev function is virtual, and meant to be overridden.
*/
function _transferToICAPWithReference(bytes32 _icap, uint _value, string _reference, address _sender) internal returns(bool) {
return proxy._forwardTransferFromToICAPWithReference(_sender, _icap, _value, _reference, _sender);
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function _performTransferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender) onlyProxy() returns(bool) {
if (isICAP(_to)) {
return _transferFromToICAPWithReference(_from, bytes32(_to) << 96, _value, _reference, _sender);
}
return _transferFromWithReference(_from, _to, _value, _reference, _sender);
}
/**
* Calls back without modifications.
*
* @return success.
* @dev function is virtual, and meant to be overridden.
*/
function _transferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender) internal returns(bool) {
return proxy._forwardTransferFromWithReference(_from, _to, _value, _reference, _sender);
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function _performTransferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference, address _sender) onlyProxy() returns(bool) {
return _transferFromToICAPWithReference(_from, _icap, _value, _reference, _sender);
}
/**
* Calls back without modifications.
*
* @return success.
* @dev function is virtual, and meant to be overridden.
*/
function _transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference, address _sender) internal returns(bool) {
return proxy._forwardTransferFromToICAPWithReference(_from, _icap, _value, _reference, _sender);
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return success.
* @dev function is final, and must not be overridden.
*/
function _performApprove(address _spender, uint _value, address _sender) onlyProxy() returns(bool) {
return _approve(_spender, _value, _sender);
}
/**
* Calls back without modifications.
*
* @return success.
* @dev function is virtual, and meant to be overridden.
*/
function _approve(address _spender, uint _value, address _sender) internal returns(bool) {
return proxy._forwardApprove(_spender, _value, _sender);
}
/**
* Passes execution into virtual function.
*
* Can only be called by assigned asset proxy.
*
* @return bytes32 result.
* @dev function is final, and must not be overridden.
*/
function _performGeneric(bytes _data, address _sender) payable onlyProxy() {
_generic(_data, msg.value, _sender);
}
modifier onlyMe() {
if (this == msg.sender) {
_;
}
}
// Most probably the following should never be redefined in child contracts.
address genericSender;
function _generic(bytes _data, uint _value, address _msgSender) internal {
// Restrict reentrancy.
require(genericSender == 0x0);
genericSender = _msgSender;
bool success = _assemblyCall(address(this), _value, _data);
delete genericSender;
_returnReturnData(success);
}
// Decsendants should use _sender() instead of msg.sender to properly process proxied calls.
function _sender() constant internal returns(address) {
return this == msg.sender ? genericSender : msg.sender;
}
// Interface functions to allow specifying ICAP addresses as strings.
function transferToICAP(string _icap, uint _value) returns(bool) {
return transferToICAPWithReference(_icap, _value, '');
}
function transferToICAPWithReference(string _icap, uint _value, string _reference) returns(bool) {
return _transferToICAPWithReference(_bytes32(_icap), _value, _reference, _sender());
}
function transferFromToICAP(address _from, string _icap, uint _value) returns(bool) {
return transferFromToICAPWithReference(_from, _icap, _value, '');
}
function transferFromToICAPWithReference(address _from, string _icap, uint _value, string _reference) returns(bool) {
return _transferFromToICAPWithReference(_from, _bytes32(_icap), _value, _reference, _sender());
}
function isICAP(address _address) constant returns(bool) {
bytes32 a = bytes32(_address) << 96;
if (a[0] != 'X' || a[1] != 'E') {
return false;
}
if (a[2] < 48 || a[2] > 57 || a[3] < 48 || a[3] > 57) {
return false;
}
for (uint i = 4; i < 20; i++) {
uint char = uint(a[i]);
if (char < 48 || char > 90 || (char > 57 && char < 65)) {
return false;
}
}
return true;
}
}
contract AssetWithAmbi is Asset, Ambi2EnabledFull {
modifier onlyRole(bytes32 _role) {
if (address(ambi2) != 0x0 && (ambi2.hasRole(this, _role, _sender()))) {
_;
}
}
}
contract AssetProxy {
function _forwardApprove(address _spender, uint _value, address _sender) returns(bool);
function _forwardTransferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender) returns(bool);
function _forwardTransferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference, address _sender) returns(bool);
function balanceOf(address _owner) constant returns(uint);
}
/**
* @title EToken2 Asset with whitelist implementation contract.
*/
contract AssetWithWhitelist is AssetWithAmbi {
mapping(address => bool) public whitelist;
uint public restrictionExpiraton;
bool public restrictionRemoved;
event Error(bytes32 _errorText);
function allowTransferFrom(address _from) onlyRole('admin') returns(bool) {
whitelist[_from] = true;
return true;
}
function blockTransferFrom(address _from) onlyRole('admin') returns(bool) {
whitelist[_from] = false;
return true;
}
function transferIsAllowed(address _from) constant returns(bool) {
return restrictionRemoved || whitelist[_from] || (now >= restrictionExpiraton);
}
function removeRestriction() onlyRole('admin') returns(bool) {
restrictionRemoved = true;
return true;
}
modifier transferAllowed(address _sender) {
if (!transferIsAllowed(_sender)) {
Error('Transfer not allowed');
return;
}
_;
}
function setExpiration(uint _time) onlyRole('admin') returns(bool) {
if (restrictionExpiraton != 0) {
Error('Expiration time already set');
return false;
}
if (_time < now) {
Error('Expiration time invalid');
return false;
}
restrictionExpiraton = _time;
return true;
}
// Transfers
function _transferWithReference(address _to, uint _value, string _reference, address _sender)
transferAllowed(_sender)
internal
returns(bool)
{
return super._transferWithReference(_to, _value, _reference, _sender);
}
function _transferToICAPWithReference(bytes32 _icap, uint _value, string _reference, address _sender)
transferAllowed(_sender)
internal
returns(bool)
{
return super._transferToICAPWithReference(_icap, _value, _reference, _sender);
}
function _transferFromWithReference(address _from, address _to, uint _value, string _reference, address _sender)
transferAllowed(_from)
internal
returns(bool)
{
return super._transferFromWithReference(_from, _to, _value, _reference, _sender);
}
function _transferFromToICAPWithReference(address _from, bytes32 _icap, uint _value, string _reference, address _sender)
transferAllowed(_from)
internal
returns(bool)
{
return super._transferFromToICAPWithReference(_from, _icap, _value, _reference, _sender);
}
}
{
"compilationTarget": {
"AssetWithWhitelist.sol": "AssetWithWhitelist"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"},{"name":"_sender","type":"address"}],"name":"_performTransferWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_proxy","type":"address"}],"name":"init","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_address","type":"address"}],"name":"isICAP","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeRestriction","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"}],"name":"blockTransferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"restrictionExpiraton","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_time","type":"uint256"}],"name":"setExpiration","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_icap","type":"string"},{"name":"_value","type":"uint256"}],"name":"transferFromToICAP","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_ambi2","type":"address"}],"name":"setupAmbi2","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_icap","type":"string"},{"name":"_value","type":"uint256"}],"name":"transferToICAP","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_icap","type":"string"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"}],"name":"transferFromToICAPWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"}],"name":"allowTransferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_icap","type":"string"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"}],"name":"transferToICAPWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"whitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_from","type":"address"}],"name":"transferIsAllowed","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_icap","type":"bytes32"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"},{"name":"_sender","type":"address"}],"name":"_performTransferToICAPWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"},{"name":"_sender","type":"address"}],"name":"_performTransferFromWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_data","type":"bytes"},{"name":"_sender","type":"address"}],"name":"_performGeneric","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_sender","type":"address"}],"name":"_performApprove","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_icap","type":"bytes32"},{"name":"_value","type":"uint256"},{"name":"_reference","type":"string"},{"name":"_sender","type":"address"}],"name":"_performTransferFromToICAPWithReference","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"proxy","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"restrictionRemoved","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_errorText","type":"bytes32"}],"name":"Error","type":"event"}]