All Products
Search
Document Center

Blockchain as a Service:Contract Interface

Last Updated:Sep 09, 2022

For the contract platform where contract-related operations are called frequently, BaaS has optimized the JS SDK to make contract operations easier and more efficient. Before you use contract-related operations, you need to understand the ABI and bytecodes. For more information, see Cloud IDE smart contract development environment.

In the following description, the sample codeCreditManager is from Solidity smart contract development.The JS SDK can be used with solc-js, a Solidity compiler. For more information about solc-js, see Compile contracts using Solidity.

Create a smart contract instance

You can run the contract code to create a smart contract instance. You can deploy and call this smart contract.

Request parameters

Parameter

Required

Type

Description

name

true

string

The name of the target smart contract. The identity of this contract is the hash value of the contract name.

abi

true

string

ABI-based string in the JSON format.

vmType

false

string

The smart contract platform supports both Solidity and C++ contract languages. To initialize a contract instance written in C++, you can configure this parameter aschain.WASM. This parameter is configured as chain.EVM by default.

Example 1

java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi)

Example 2

Use the Wasm bytecode to initialize a contract written in C++.

java script
const wasm_code = fs.readFileSync('./contract/base.wasm')
const abi = fs.readFileSync('./contract/base.abi')
const bytecode = '0x'+wasm_code.toString('hex')

// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi, chain.WASM)

Deploy smart contracts

You can call the new operation to deploy a smart contract.

Request parameters

Parameter

Required

Type

Description

bytecode

true

string

The bytecode of the target smart contract. The bytecode is in the hexadecimal format without the “0x” prefix.

data

true

object

Contains fields such as ‘from’ and ‘parameters’.

Content of the data field

Field

Required

Type

Description

from

true

string

The current account name to be configured.

parameters

true

Array

If the smart contract contains an init() function and this function requires a list of parameters, this list can be passed in through the parameters field.

Examples

java script
const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

// Add a timestamp to make sure that the identity of the contract name is unique
const contractName = 'contract'+Date.now()
// Initialize a smart contract instance
let myContract = chain.ctr.contract(contractName, abi) 
// Deploy a smart contract. Parameters required by the init() function can be passed in.
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
})

Call smart contracts

Use the name of the target contract method to call the contract method.

Request parameters

Parameter

Required

Type

Description

parameters

false

Not specified

See the parameter list of a specific contract method. The number of parameters varies with the contract method.

data

true

object

Contains the from field.

Content of the data field

Field

Required

Type

Description

from

true

string

The current account name to be configured.

Example 1

Call a contract method when deploying the callback function of the contract:

java script
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
  // Two parameters are required when calling the Issue contract method: the account identity and a numerical value.
  myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
    console.log('output is:', output)
  })
})

Example 2

Call a contract method after the contract has been deployed. In case of multiple contracts, these contracts are called concurrently. If a call dependency exists, use the callback function.

java script
myContract.new(bytecode, {
  from: 'Tester001',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
})

// Call the ‘Issue’ contract method 
myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
  console.log('output is:', output)
})

Update smart contracts

You can call the update operation to update a contract that exists on a blockchain. Update smart contracts with caution. The update of contracts needs to be compatible with the data storage of the new contracts and the old contract. Under normal circumstances, we recommend that you do not use this update feature.

Request parameters

Parameter

Required

Type

Description

bytecode

true

string

The bytecode of the target smart contract. The bytecode is in the hexadecimal format without the 0x prefix.

data

true

object

An empty object.

Examples

Call a contract method when deploying the callback function of the contract:

java script
myContract.update(bytecode, {}
, (err, contract, data) => {
  console.log('contract update result:', data)
})
Note

To update the contract, the compiled runtime bytecode is required. This bytecode can be obtained directly by using the --bin-runtime parameter of solc compiler, the Solidity compiler. It is the subset of the bytecode of the compiled --bin parameter. The runtime bytecode can also be obtained by deploying local contracts.

Examples

Obtain the runtime bytecode by deploying a contract or using solc-js to update a contract:In JavaScript syntax, solc-js uses the --bin parameter to compile a contract into bytecode by default. This bytecode cannot be used directly to update a contract. However, the runtime bytecode obtained after deploying a contract can be used to update the contract.

Note

It is only applicable to Solidity-0.4.24 version. For versions 0.6.4 and above, please use the Solidity compiler (solc) to obtain the runtime bytecode.

Use solc-js to update smart contracts as follows:

  1. Use solc-js to compile contract A

  2. Deploy smart contract A

  3. Call smart contract A

  4. Modify the smart contract code to obtain smart contract A’

  5. Use solc-js to compile smart contract A’

  6. Deploy the smart contract A’ locally and obtain the runtime bytecode.

  7. Use the A’ runtime bytecode to update smart contract A.

  8. Call smart contract A to verify the update status.

const solc = require('@alipay/solc')
const contract = fs.readFileSync('. /CreditManager.sol', {encoding: 'ascii'})
// Set the second parameter to 1 to start compiling
const output = solc.compile(contract, 1)
const abi = JSON.parse(output.contracts[':CreditManager'].interface)
const bytecode = output.contracts[':CreditManager'].bytecode

console.log('bytecode:', bytecode)
// Add a timestamp to make sure that the identity of the contract name is unique
let contractName = 'contract'+Date.now()
let myContract = chain.ctr.contract(contractName, abi)

// Use the bytecode compiled by solc-js to upgrade contracts
myContract.new(bytecode, {
  from: 'Tester001',
}, (err, contract, data) => {
  console.log('contract new:', data)
  myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
    console.log('output1 is:', output)

    //Change the calculation logic of the contract named CreditManager.sol to obtain a contract named CreditManagerPro.sol. Note that the contract storage definition cannot be changed.
    //In the Issue method: change `credit[account] += value;` to `credit[account] += value * 2;`
    const contract_pro = fs.readFileSync('. /CreditManagerPro.sol', {encoding: 'ascii'})
    // Set the second parameter to 1 to start compiling
    const output_pro = solc.compile(contract_pro, 1)
    const abi_pro = JSON.parse(output_pro.contracts[':CreditManager'].interface)
    const bytecode_pro = output_pro.contracts[':CreditManager'].bytecode
    myContract = chain.ctr.contract(contractName, abi_pro)

    myContract.new(bytecode_pro, {
      from: 'Tester001',
      local: true,  //Deploy a contract locally to obtain the `runtime` bytecode
      block_number: 0 //Use a genesis block to deploy the contract locally to avoid conflict contract IDs.
    }, (err, contract, data) => {
      console.log('local contract new result:', data)

      // Use the obtained `runtime` bytecode to upgrade the contract
      myContract.update(data.receipt.output.replace('0x' + chain.EVM, ''), {
      }, (err, contract, data) => {
        console.log('contract update result:', data)

        // Call the updated contract to issue credits
        myContract.Issue('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', 100 , { from: 'Tester001' }, (err, output, data) => {
          console.log('output2 is:', output.toString())

          // View the credits that have been issued to the target account. If the contract is updated successfully, the result is 300.
          myContract.Query('0xc60a9d48105950a0cca07a4c6320b98c303ad42d694a634529e8e1a0a16fcdb5', { from: 'Tester001' }, (err, output, data) => {
            console.log('output3 is:', output.toString())
          })
        })
      })
    })
  })


})

Results:

...
contract update result: { msg_type: 63,
  sequence: 7,
  return_code: 0,
  group_id: '0x0000000000000000000000000000000000000000',
  receipt:
   { result: 0,
     gas_used: 28610,
     log_entry: [ [Object] ],
     output: '' },
  block_number: 86114,
  transaction_index: 0,
  api: 'QueryTransactionReceipt',
  txhash:
   '0x40a72b99ec64fca0e1cc5025920de086a2523b4761ea5020c0f43a5240dc754a' }
output2 is: true
output3 is: 300