Created
January 30, 2019 21:16
-
-
Save recmo/ec5b39e4cfc047df7629eb13c27034f1 to your computer and use it in GitHub Desktop.
ShardToken: Actor Model through Cousin Proofs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract ShardToken { | |
address OWNER; | |
address ROOT; | |
uint256[] ANCESTRY_PROOF; | |
address owner; | |
uint256 next_nonce; | |
uint256 balance; | |
mapping (address => uint256) allowance; | |
modifier only_owner() { | |
require(msg.sender == OWNER, "ONLY_OWNER"); | |
} | |
modifier only_relatives(uint256[] memory proof) { | |
require(related(msg.sender, proof), "NOT_RELATED"); | |
} | |
constructor( | |
address owner, | |
address root, | |
uint256[] ancestry_proof, | |
uint amount) | |
{ | |
OWNER = owner; | |
ANCESTRY_PROOF = ancestry_proof; | |
next_nonce = 0; | |
// | |
assert(related(this, ANCESTRY_PROOF), "INVALID_PROOF"); | |
} | |
// Allows anyone to create a new empty wallet for this | |
// token. | |
function create() | |
public | |
returns (address new_wallet) | |
{ | |
address owner = msg.sender; | |
uint256 nonce = next_nonce; | |
next_nonce += 1; | |
new_wallet = new ShardToken( | |
owner, | |
ROOT, | |
ANCESTRY_PROOF + [next_nonce], | |
amount | |
); | |
assert(new_wallet == child_address(this, child_nonce)); | |
} | |
function destroy() | |
public | |
only_owner() | |
{ | |
} | |
// Transfer to some other wallet | |
function transfer( | |
ShardToken receipient, | |
uint256 amount | |
) | |
public | |
only_owner() | |
{ | |
require(balance > amount, "INSUFFICIENT_FUNDS"); | |
balance -= amount; | |
receipient.receive(amount, ANCESTRY_PROOF); | |
} | |
function receive( | |
uint256 amount, | |
uint256[] ancestry_proof | |
) | |
public | |
only_relatives(ancestry_proof) | |
{ | |
balance += amount; | |
// Should not happen because total supply guarantees an upper limit. | |
assert(balance > amount, "BALANCE_OVERFLOW"); | |
} | |
/// Check if a given contract is a sibbling | |
/// @param sibbling The constract address to check for familiar ties. | |
/// @param nonces Claimed proof of ancenstry. | |
function related( | |
address sibbling, | |
uint256[] nonces | |
) | |
internal pure | |
returns (bool) | |
{ | |
address relative = ROOT; | |
for (uint256 i = 0; i < nonces.length; ++i) { | |
relative = child_address(relative, nonces[i]); | |
} | |
return relative == sibbling; | |
} | |
// Todo: | |
// https://github.com/projectchicago/gastoken/blob/master/contract/rlp.sol#L21 | |
function child_address( | |
address parent, | |
uint256 nonce | |
) | |
internal pure | |
returns (address) | |
{ | |
bytes32 code_hash = code_hash(this); | |
bytes32 hash = keccak256(abi.encodePacked( | |
bytes1(0xff), | |
parent, | |
nonce, | |
code_hash | |
)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment