pragma solidity = 0.6.0;
contract ProtectedAddressPers
{
address private root;
address private control;
uint private period;
uint private withdrawDate;
event log420 ( address indexed, address, uint );
constructor ( address _root, address _control, uint _period ) public
{
root = _root;
control = _control;
period = _period;
withdrawDate = block.timestamp;
}
receive () external payable
{
emit log420 ( address(this), msg.sender, msg.value );
}
fallback () external
{
address core = address(0);
(bool ret, bytes memory _data) = root.staticcall ( abi.encodeWithSignature ( "getAddress(string)", "pCoreAddress" ) );
require ( ret, "PAMSG001" );
assembly
{
core := mload ( add ( _data, 32 ) )
let ptr := mload ( 0x40 )
calldatacopy ( ptr, 0, calldatasize() )
let result := delegatecall ( gas(), core, ptr, calldatasize(), 0, 0 )
let size := returndatasize ()
returndatacopy ( ptr, 0, size )
switch result
case 0
{
revert ( ptr, size )
}
default
{
return ( ptr, size )
}
}
}
}
// ----------------------------------------------------------------------------
// MCWS Counter Address
// https://mycoldwallet.io
// ----------------------------------------------------------------------------
interface CounterAddress
{
function getInfo ( string calldata _key ) external view returns ( string memory, uint );
function isWorker ( address _worker ) external view returns ( bool );
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ----------------------------------------------------------------------------
interface ERC20Interface
{
function totalSupply () external view returns ( uint );
function balanceOf ( address tokenOwner ) external view returns ( uint balance );
function allowance ( address tokenOwner, address spender ) external view returns ( uint remaining );
function transfer ( address to, uint tokens ) external returns ( bool success );
function approve ( address spender, uint tokens ) external returns ( bool success );
function transferFrom ( address from, address to, uint tokens ) external returns ( bool success );
}
contract ProtectedAddressCore
{
address private root;
address private control;
uint private period;
uint private withdrawDate;
string constant private name = "MCWS ProtectedAddress";
string constant private ver = "0.9";
address private manager;
event log400 ( address indexed, address, address, uint, uint );
event log401 ( address indexed, address, uint, uint );
event log402 ( address indexed, uint, uint, uint );
event log403 ( address indexed, uint, uint, uint, uint );
event log404 ( address indexed, address, address, uint, uint );
event log410 ( address indexed, address, uint );
event log430 ( address, address, uint, uint );
event log440 ( address indexed, uint, uint );
event log441 ( address indexed, address, address );
constructor () public
{
manager = msg.sender;
}
modifier onlyManager { require ( msg.sender == manager, "PAMSG002" ); _; }
modifier onlyWorker { require ( CounterAddress(getCounter()).isWorker(msg.sender), "PAMSG003" ); _; }
modifier onlyController { require ( msg.sender == control, "PAMSG004" ); _; }
modifier onlyInPeriod { require ( block.timestamp <= withdrawDate + period, "PAMSG005" ); _; }
modifier onlyOutPeriod { require ( block.timestamp > withdrawDate + period, "PAMSG006" ); _; }
receive () external payable {}
function getWithdrawDate () external view returns ( uint, uint, uint )
{
return ( block.timestamp, withdrawDate, period );
}
function getAddresses () external view returns ( address, address )
{
return ( root, control );
}
function getInfo () external pure returns ( string memory, string memory )
{
return ( name, ver );
}
function getCounter () private view returns ( address _counter )
{
(, bytes memory _data) = root.staticcall ( abi.encodeWithSignature ( "getAddress(string)", "counterAddress" ) );
assembly { _counter := mload ( add ( _data, 32 ) ) }
}
function setRoot ( address _root ) external payable onlyManager
{
root = _root;
}
function changePeriodByMCWS ( uint _period ) external payable onlyWorker onlyOutPeriod
{
emit log440 ( address(this), period, _period );
withdrawDate = block.timestamp;
period = _period;
}
function changeControllerByMCWS ( address _newControl, uint _period ) external payable onlyWorker onlyOutPeriod
{
if ( _period > 0 )
{
emit log440 ( address(this), period, _period );
period = _period;
}
emit log441 ( address(this), control, _newControl );
control = _newControl;
withdrawDate = block.timestamp;
}
function chargeGas ( uint _amount ) external payable onlyController onlyInPeriod
{
require ( address(this).balance >= _amount, "PAMSG007" );
(bool _ret, bytes memory _message ) = payable(control).call.value ( _amount ) ( "" );
require ( _ret, string(_message) );
emit log410 ( address(this), control, _amount );
}
function transfer ( address _target, uint _amount ) external payable onlyController onlyInPeriod
{
address counter = getCounter ();
(,uint fees) = CounterAddress(counter).getInfo ( "transfer" );
require ( address(this).balance >= fees + _amount, "PAMSG008" );
(bool _ret, bytes memory _message ) = payable(counter).call.value ( fees ) ( "" );
require ( _ret, string(_message) );
(bool _ret2, bytes memory _message2 ) = payable(_target).call.value ( _amount ) ( "" );
require ( _ret2, string(_message2) );
emit log401 ( address(this), _target, _amount, fees );
withdrawDate = block.timestamp;
}
function transferToken ( address _tokenContract, address _targetToken, uint _amount ) external payable onlyController onlyInPeriod
{
address counter = getCounter ();
(,uint fees) = CounterAddress(counter).getInfo ( "transfer" );
require ( address(this).balance >= fees, "PAMSG009" );
(bool _ret, bytes memory _message ) = payable(counter).call.value ( fees ) ( "" );
require ( _ret, string(_message) );
ERC20Interface tokenContract = ERC20Interface ( _tokenContract );
uint balance = tokenContract.balanceOf ( address(this) );
require ( balance >= _amount, "PAMSG010" );
tokenContract.transfer ( _targetToken, _amount );
emit log430 ( _tokenContract, _targetToken, _amount, fees );
withdrawDate = block.timestamp;
}
function requestNewProtectedAddress ( uint _period ) external payable
{
//RootAddress root = RootAddress ( root );
//address notiAddress = root.getAddress ( 'notiAddress' );
//NotificationAddress noti = NotificationAddress ( notiAddress );
//(,uint fees) = noti.viewFees ( "newProtected" );
//require ( msg.value == fees, "Invalid fees" );
//(bool _ret, bytes memory _message ) = payable ( root.getAddress ( 'counterAddress' ) ).call.value ( msg.value ) ( "" );
//require ( _ret, string(_message) );
ProtectedAddressPers newPAPers = new ProtectedAddressPers ( root, msg.sender, _period );
emit log400 ( address(newPAPers), address(msg.sender), address(newPAPers), _period, msg.value );
}
function requestChangePeriod ( address _targetPA, uint _period, uint _extendedFees ) external payable onlyController
{
address counter = getCounter ();
(,uint fees) = CounterAddress(counter).getInfo ( "changePeriod" );
require ( address(this).balance >= fees + _extendedFees, "PAMSG012" );
(bool _ret, bytes memory _message ) = payable(counter).call.value ( fees + _extendedFees ) ( "" );
require ( _ret, string(_message) );
if ( block.timestamp <= withdrawDate + period )
{
emit log402 ( _targetPA, period, _period, fees );
period = _period;
withdrawDate = block.timestamp;
}
else
emit log403 ( _targetPA, period, _period, fees, _extendedFees );
}
function requestChangeController ( address _targetPA, address _newController, uint _extendedFees ) external payable onlyController onlyInPeriod
{
address counter = getCounter ();
(,uint fees) = CounterAddress(counter).getInfo ( "changeController" );
require ( address(this).balance >= fees + _extendedFees, "PAMSG013" );
(bool _ret, bytes memory _message ) = payable(counter).call.value ( fees + _extendedFees ) ( "" );
require ( _ret, string(_message) );
(,address _control) = ProtectedAddressCore(payable(_targetPA)).getAddresses ();
emit log404 ( _targetPA, _control, _newController, fees, _extendedFees );
}
}
{
"compilationTarget": {
"browser/ProtectedAddress.sol": "ProtectedAddressCore"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log400","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log401","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log402","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log403","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log404","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log410","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log430","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"log440","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"address","name":"","type":"address"}],"name":"log441","type":"event"},{"inputs":[{"internalType":"address","name":"_newControl","type":"address"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"changeControllerByMCWS","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"changePeriodByMCWS","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"chargeGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAddresses","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInfo","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getWithdrawDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_targetPA","type":"address"},{"internalType":"address","name":"_newController","type":"address"},{"internalType":"uint256","name":"_extendedFees","type":"uint256"}],"name":"requestChangeController","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_targetPA","type":"address"},{"internalType":"uint256","name":"_period","type":"uint256"},{"internalType":"uint256","name":"_extendedFees","type":"uint256"}],"name":"requestChangePeriod","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"requestNewProtectedAddress","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_root","type":"address"}],"name":"setRoot","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"address","name":"_targetToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]