【0092】
付録1
contract coreledger
{
mapping (bytes32 => uint) public Account;
mapping (uint80 => ASSET) public Asset;
mapping (bytes32 => AMENDMENT) public Amendment;
uint16 public LedgerId;
string public ContractVersion;
string public DocumentDataURI;
uint80 public SupplyLength;
mapping (bytes32 => SUPPLY) public Supply;
uint public DecimalPointer;
/* ###################### Data Structures ###################### */
struct ASSET
{
address Issuer;
bytes32 Hash;
uint256 CreatedOn;
uint256 TotalTokens;
bool BitWise;
}
struct SUPPLY
{
address Owner;
bytes32 ExtReference;
uint80 OfferedAssetID;
uint80 DesiredAssetID;
address DesiredAddress;
uint OpenAmount;
uint ExchangeRate;
bool TakeAll;
uint8 Type;
}
struct AMENDMENT
{
uint80 AssetId;
bytes32 Hash;
uint256 CreatedOn;
}
/* ###################### Initialization ###################### */
function coreledger()
{
LedgerId=1;
ContractVersion="0.7.9";
DecimalPointer=10000000000;
SupplyLength=0;
}
/* ###################### AMENDMENTS ###################### */
function CreateAmendment(uint80 _assetId, uint160 _amendmentId, bytes32 _hash)
{
bytes32 amendmentId = toAmendmentId(_amendmentId,_assetId);
if(msg.sender==Asset[_assetId].Issuer&&Amendment[amendmentId].Hash==0x0)
{
Amendment[amendmentId]=AMENDMENT({
AssetId:_assetId,
Hash:_hash,
CreatedOn:block.number
});
}
}
function GetAmendment(bytes32 _amendmentId) constant returns (uint80 assetId, bytes32 hash, uint createdon)
{
assetId=Amendment[_amendmentId].AssetId;
hash=Amendment[_amendmentId].Hash;
createdon=Amendment[_amendmentId].CreatedOn;
}
/* ###################### ASSET HANDLING ###################### */
function CreateAndActivateAsset(uint80 _assetId, bytes32 _hash, bool _bitWise) returns (bool result)
{
if(Asset[_assetId].Issuer==0x0)
{
Asset[_assetId]=ASSET({
Issuer:msg.sender,
Hash:_hash,
CreatedOn:block.number,
TotalTokens:0,
BitWise:_bitWise
});
result=true;
}
}
function IssueTokens(uint80 _assetId, uint _units) returns (bool result)
{
if(Asset[_assetId].Issuer==msg.sender)
{
bytes32 accountid=toAccountId(msg.sender,_assetId);
Asset[_assetId].TotalTokens+=_units;
Account[accountid]+=_units;
result=true;
}
}
function DestroyTokens(uint80 _assetId, uint _units) returns (bool result)
{
if(Asset[_assetId].Issuer==msg.sender)
{
bytes32 accountid=toAccountId(msg.sender,_assetId);
if(Account[accountid]>=_units)
{
Asset[_assetId].TotalTokens-=_units;
Account[accountid]-=_units;
result=true;
}
}
}
function HasEnoughTokens(uint80 _assetId,bytes32 _accountid,uint _units) constant returns (bool result)
{
if(Asset[_assetId].Issuer>0x0)
{
if(Account[_accountid]>=_units)
{
result=true;
}
}
}
function TransferTokens(uint80 _assetId,address _receiver,uint _units) returns (bool result)
{
if(_assetId==1 || Asset[_assetId].Issuer>0x0)
{
bytes32 accountIdSender=toAccountId(msg.sender,_assetId);
bytes32 accountIdReceiver=toAccountId(_receiver,_assetId);
if(HasEnoughTokens(_assetId,accountIdSender,_units))
{
Account[accountIdSender]-=_units;
Account[accountIdReceiver]+=_units;
result=true;
}
}
}
/* ###################### SUPPLY ###################### */
function CreateSupply(uint80 _offeredAssetID, uint80 _desiredAssetID, address _desiredAddress, uint _exchangerate, uint _maximumAmount, bytes32 _extReference, bool _takeAll) returns (bytes32)
{
bytes32 _offeredAssetAccountID=toAccountId(msg.sender,_offeredAssetID);
if(_desiredAddress==0x0)
{
_desiredAddress=msg.sender;
}
if(HasEnoughTokens(_offeredAssetID,_offeredAssetAccountID,_maximumAmount))
{
bytes32 _supplyId = toSupplyId(_desiredAssetID, _offeredAssetID, SupplyLength++);
Supply[_supplyId]=SUPPLY({
Owner:msg.sender,
OfferedAssetID:_offeredAssetID,
DesiredAssetID:_desiredAssetID,
DesiredAddress:_desiredAddress,
OpenAmount:_maximumAmount,
ExchangeRate:_exchangerate,
ExtReference:_extReference,
TakeAll:_takeAll,
Type:0
});
return _supplyId;
}
}
function ConsumeSupply(bytes32 _supplyId,uint _inputAmount) internal returns (uint outputAmount, uint80 outputAssetId)
{
outputAmount=0;
outputAssetId=0;
if(Supply[_supplyId].Owner>0x0 && Supply[_supplyId].OpenAmount>0 && Supply[_supplyId].Type==0)
{
bytes32 offeredAssetAccountID=toAccountId(Supply[_supplyId].Owner,Supply[_supplyId].OfferedAssetID);
bytes32 desiredAssetAccountID=toAccountId(Supply[_supplyId].DesiredAddress,Supply[_supplyId].DesiredAssetID);
outputAmount=(_inputAmount*Supply[_supplyId].ExchangeRate/DecimalPointer);
if(outputAmount>0 &&
Account[offeredAssetAccountID]>=outputAmount &&
Supply[_supplyId].OpenAmount>=outputAmount &&
(Supply[_supplyId].TakeAll==false || Supply[_supplyId].TakeAll==true && Supply[_supplyId].OpenAmount==outputAmount))
{
Account[offeredAssetAccountID]-=outputAmount;
Account[desiredAssetAccountID]+=_inputAmount;
Supply[_supplyId].OpenAmount-=outputAmount;
outputAssetId=Supply[_supplyId].OfferedAssetID;
}
else
{
outputAmount=0;
outputAssetId=0;
}
}
}
/* ###################### WARP ###################### */
function StartWARP(bytes32[] _supplyIds, uint _inputAmount) internal returns (uint outputAmount, uint80 outputAssetId)
{
bytes32 CallerPayFromAccountID=toAccountId(msg.sender,Supply[_supplyIds[0]].DesiredAssetID);
if(!HasEnoughTokens(Supply[_supplyIds[0]].DesiredAssetID,CallerPayFromAccountID,_inputAmount))
{
throw;
}
Account[CallerPayFromAccountID]-=_inputAmount;
outputAmount=0;
outputAssetId=Supply[_supplyIds[0]].DesiredAssetID;
for(uint i=0;i<_supplyIds.length;i++)
{
if(Supply[_supplyIds[i]].DesiredAssetID!=outputAssetId)
{
throw;
}
(outputAmount,outputAssetId)=ConsumeSupply(_supplyIds[i],_inputAmount);
if(outputAmount<1)
{
throw;
}
_inputAmount=outputAmount;
}
}
function RunWARP(bytes32[] _supplyIds, uint _inputAmount) returns (bool success)
{
success=false;
uint outputAmount=0;
uint80 outputAssetId=0;
(outputAmount,outputAssetId) = StartWARP(_supplyIds,_inputAmount);
if(outputAmount>0)
{
bytes32 CallerReceiveToAccountID=toAccountId(msg.sender,outputAssetId);
Account[CallerReceiveToAccountID]+=outputAmount;
success=true;
}
else
{
throw;
}
}
/* ###################### ID functions ###################### */
function toAccountId(address _owner, uint80 _assetId) constant returns (bytes32 result)
{
result=0x0;
uint[] memory temp=new uint[](4);
temp[0]=uint(_owner);
temp[1]=0;
temp[2]=uint(_assetId);
temp[3]=LedgerId;
assembly
{
result:=add(add(mload(add(temp,44)),mload(add(temp,98))),mload(add(temp,128)))
}
}
function toInvoiceId(address _receiverAddress, uint80 _externalId) constant returns (bytes32 result)
{
return toAccountId(_receiverAddress,_externalId);
}
function toAmendmentId(uint160 _count, uint80 _assetId) constant returns (bytes32 result)
{
result=0x0;
uint[] memory temp=new uint[](4);
temp[0]=uint(_count);
temp[1]=0;
temp[2]=uint(_assetId);
temp[3]=LedgerId;
assembly
{
result:=add(add(mload(add(temp,44)),mload(add(temp,98))),mload(add(temp,128)))
}
}
function extractBytes32Schematics(bytes32 _input) constant returns(address addressPart,uint80 bigIntPart, uint16 ledgerPart)
{
uint256 tempStorage;
addressPart=0x0;
bigIntPart=0;
ledgerPart=0;
uint[] memory temp=new uint[](3);
temp[0]=0;
temp[1]=uint(_input);
temp[2]=0;
assembly
{
addressPart:=mload(add(temp,52))
}
assembly
{
tempStorage:=mload(add(temp,84))
}
temp[1]=tempStorage;
assembly
{
bigIntPart:=mload(add(temp,42))
tempStorage:=mload(add(temp,74))
}
temp[1]=tempStorage;
assembly
{
ledgerPart:=mload(add(temp,34))
}
}
function toSupplyId(uint80 _assetIdDesired, uint80 _assetIdOffered, uint80 _count) constant returns (bytes32 result)
{
result=0x0;
uint[] memory temp=new uint[](11);
temp[0]=uint(_assetIdDesired);
temp[1]=0;
temp[2]=1;
temp[3]=0;
temp[4]=uint(_assetIdOffered);
temp[5]=0;
temp[6]=1;
temp[7]=0;
temp[8]=uint(_count);
assembly
{
result:=add(add(add(add(mload(add(temp,54)),mload(add(temp,116))),mload(add(temp,170))),mload(add(temp,232))),mload(add(temp,288)))
}
}
}