Skip to content

Deploy smart contract using solc

cross-chain edited this page Mar 4, 2020 · 2 revisions

Deploy smart contract on Fusion blockchain using solc

1. Install solc

# the latest version may not support
npm install -g [email protected]

2. Add contract file

In our example, we add file FSNExample.sol. Please reference to FIP-0001-Smart-contract-support-timelock-and-asset for more info about this contract.

FSNExample.sol

pragma solidity <=0.5.12;

contract FSNContract {
    address constant precompile = address(0x9999999999999999999999999999999999999999);

    // these events will be generated by the low level impl.
    event LogFusionAssetReceived(bytes32 indexed _asset, address indexed _from, uint256 _value, uint64 _start, uint64 _end, SendAssetFlag _flag);
    event LogFusionAssetSent(bytes32 indexed _asset, address indexed _to, uint256 _value, uint64 _start, uint64 _end, SendAssetFlag _flag);

    enum SendAssetFlag {
        UseAny,                                         // 0
        UseAnyToTimeLock,                // 1
        UseTimeLock,                             // 2
        UseTimeLockToTimeLock,    // 3
        UseAsset,                                      // 4
        UseAssetToTimeLock              // 5
    }

    function _sendAsset(bytes32 asset, address to, uint256 value, uint64 start, uint64 end, SendAssetFlag flag) internal returns (bool, bytes memory) {
        bytes memory input = abi.encode(1, asset, to, value, start, end, flag);
        return precompile.call(input);
    }
}

contract FSNExample is FSNContract {
    address owner;
    modifier onlyOwner {
        require(msg.sender == owner, "only owner");
        _;
    }

    constructor() public {
        owner = msg.sender;
    }

    // If a contract want to receive Fusion Asset and TimeLock from an EOA,
    // the contract must impl the following 'receiveAsset' interface.
    function receiveAsset(bytes32 assetID, uint64 startTime, uint64 endTime, SendAssetFlag flag, uint256[] memory extraInfo) payable public returns (bool success) {
        (assetID, startTime, endTime, flag, extraInfo); // silence warning of Unused function parameter
        return true;
    }

    // impl by calling a precompiled contract '0x9999999999999999999999999999999999999999'
    // which support send out Fusion Asset and TimeLock from the calling contract.
    function sendAsset(bytes32 asset, address to, uint256 value, uint64 start, uint64 end, SendAssetFlag flag) onlyOwner public returns (bool success) {
        (success,) = _sendAsset(asset, to, value, start, end, flag);
        require(success, "call sendAsset failed");
        return true;
    }
}

2. Compile contract

solcjs --abi --bin --optimize ./FSNExample.sol -o .

After building, it will generate the corresponding ABI and BIN files for each contrtact definition:

__FSNExample_sol_FSNContract.abi
__FSNExample_sol_FSNContract.bin
__FSNExample_sol_FSNExample.abi
__FSNExample_sol_FSNExample.bin

We only care about ABI and BIN of the derivative contract (__FSNExample_sol_FSNExample.abi and __FSNExample_sol_FSNExample.bin) and ignore base contract's ABI and BIN.

3. Deploy contract

We deploy contract by attaching to the running Fusion blockchain node and create contract by the inner Web3 methods.

a) attach to the running node

./efsn attach node1/efsn.ipc

b) create contract

//... - is content of file `__FSNExample_sol_FSNExample.abi`
abi = ... 

MyContract = eth.contract(abi)

// sender_address - you should specify your own address
// ...  - is 0x plus content of file `__FSNExample_sol_FSNExample.bin`
myContract = MyContract.new({from:"sender_address",gas:3000000,data:"..."}) 

We can check the contract creation transaction detail by hash myContract.transactionHash. If contract is deployed successfully, myContract.address will be the contract's address which is undefined otherwise.

c) call contract

If we are still in the above attaching, we could use myContract directly to call its methods. If we have dettached from the above attaching, we need re-attach and do the following assignment:

// abi  - is content of file `__FSNExample_sol_FSNExample.abi`
// contractAddress -  is the deployed contract's address
myContract = eth.contract(abi).at(contractAddress)

Call method receiveAsset (call other methods is likely):

// use `call` to do some checking first
myContract.receiveAsset.call("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",0,1614671636,0,[],{from:eth.coinbase,value:web3.toWei(10)})

// if passed, replace `call` with `sendTransaction` to make transaction
myContract.receiveAsset.sendTransaction("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",0,1614671636,0,[],{from:eth.coinbase,value:web3.toWei(10)})

We can use eth.getTransaction and eth.getTransactionReceipt to check the detail transaction status. logs and other info.