# 智能合约

智能合约模块提供了合约的部署、调用、查询等完整功能支持。

## 合约部署

### 创建合约
```javascript
// 创建合约操作
const createContractOperation = {
  sourceAddress: sourceAddress,    // 合约创建者地址
  initBalance: '1000000',         // 合约初始化余额
  type: 0,                        // 合约类型，0表示JavaScript
  payload: contractCode,          // 合约代码
  initInput: 'init-args',         // 可选，合约初始化参数
  metadata: 'contract info'       // 可选，合约备注
};

// 提交创建合约操作
const response = yield sdk.operation.contract.create(createContractOperation);

// 获取合约地址
const contractAddress = yield sdk.contract.getAddress({
  hash: response.result.hash      // 合约创建交易的hash
});
```

### 合约代码示例
```javascript
// 简单的Token合约示例
'use strict';

const contractCode = `
function init(input) {
  let params = JSON.parse(input);
  Chain.store('totalSupply', params.totalSupply);
  Chain.store('name', params.name);
  Chain.store('symbol', params.symbol);
  Chain.store('decimals', params.decimals);
  Chain.store(Chain.thisAddress, params.totalSupply);
}

function main(input) {
  let params = JSON.parse(input);
  if (params.method === 'transfer') {
    return transfer(params);
  } else if (params.method === 'balanceOf') {
    return balanceOf(params);
  }
  throw 'Unknown method';
}

function transfer(params) {
  let from = Chain.thisAddress;
  let to = params.to;
  let value = params.value;
  
  let fromBalance = Chain.load(from);
  let toBalance = Chain.load(to) || '0';
  
  if (Number(fromBalance) < Number(value)) {
    throw 'Insufficient balance';
  }
  
  Chain.store(from, String(Number(fromBalance) - Number(value)));
  Chain.store(to, String(Number(toBalance) + Number(value)));
  return true;
}

function balanceOf(params) {
  let address = params.address;
  let balance = Chain.load(address) || '0';
  return balance;
}

function query(input) {
  let params = JSON.parse(input);
  if (params.method === 'balanceOf') {
    return balanceOf(params);
  }
  throw 'Unknown method';
}
`;
```

## 合约调用

### 通过BU调用合约
```javascript
// 使用调用合约
const invokeByOPOperation = {
  sourceAddress: sourceAddress,    // 调用者地址
  contractAddress: contractAddr,   // 合约地址
  buAmount: '100',                // 调用时转入的BU数量
  input: JSON.stringify({         // 调用参数
    method: 'transfer',
    to: 'destinationAddress',
    value: '100'
  })
};

const buResponse = yield sdk.operation.contract.invokeByBU(invokeByOPOperation);
```

### 通过资产调用合约
```javascript
// 使用资产调用合约
const invokeByAssetOperation = {
  sourceAddress: sourceAddress,    // 调用者地址
  contractAddress: contractAddr,   // 合约地址
  code: 'CNY',                    // 资产代码
  issuer: 'issuer-address',       // 资产发行方地址
  assetAmount: '100',             // 调用时转入的资产数量
  input: JSON.stringify({         // 调用参数
    method: 'transfer',
    to: 'destinationAddress',
    value: '100'
  })
};

const assetResponse = yield sdk.operation.contract.invokeByAsset(invokeByAssetOperation);
```

## 合约查询

### 查询合约信息
```javascript
// 查询合约基本信息
const contractInfo = yield sdk.contract.getInfo(contractAddress);

// 查询合约地址
const contractAddress = yield sdk.contract.getAddress({
  hash: contractCreateHash        // 合约创建交易的hash
});
```

### 调用合约查询接口
```javascript
// 调用合约的查询方法
const contractCallResponse = yield sdk.contract.call({
  contractAddress: contractAddress,
  input: JSON.stringify({
    method: 'balanceOf',
    address: 'queryAddress'
  })
});
```

## 合约事件

### 创建合约日志
```javascript
// 创建合约日志
const createLogOperation = {
  sourceAddress: sourceAddress,    // 日志创建者地址
  topic: 'event-topic',           // 日志主题
  data: 'event-data'              // 日志数据
};

const logResponse = yield sdk.operation.log.create(createLogOperation);
```

### 查询合约日志
```javascript
// 查询合约日志
const logs = yield sdk.operation.log.getEvents({
  contractAddress: contractAddress,
  topic: 'event-topic'
});
```

## 最佳实践

1. 合约开发规范
   ```javascript
   // 标准合约结构
   const standardContract = `
   'use strict';
   
   // 初始化函数
   function init(input) {
     // 验证输入参数
     if (!input) throw 'Invalid input';
     // 初始化存储
   }
   
   // 主函数 - 处理所有写操作
   function main(input) {
     // 解析输入
     let params = JSON.parse(input);
     // 方法路由
     switch(params.method) {
       case 'method1': return method1(params);
       case 'method2': return method2(params);
       default: throw 'Unknown method';
     }
   }
   
   // 查询函数 - 处理只读操作
   function query(input) {
     // 解析输入
     let params = JSON.parse(input);
     // 查询路由
     switch(params.method) {
       case 'query1': return query1(params);
       case 'query2': return query2(params);
       default: throw 'Unknown query method';
     }
   }
   `;
   ```

2. 错误处理
   ```javascript
   // 合约中的错误处理
   function safeOperation(params) {
     // 参数验证
     if (!params.value || params.value <= 0) {
       throw 'Invalid value';
     }
     
     // 状态检查
     let state = Chain.load('state');
     if (state !== 'active') {
       throw 'Contract not active';
     }
     
     // 余额检查
     let balance = Chain.load(params.address);
     if (Number(balance) < Number(params.value)) {
       throw 'Insufficient balance';
     }
     
     // 执行操作
     try {
       // 业务逻辑
     } catch (e) {
       throw 'Operation failed: ' + e;
     }
   }
   ```

3. 存储优化
   ```javascript
   // 优化存储结构
   function optimizedStorage() {
     // 使用前缀区分不同类型的数据
     Chain.store('balance:' + address, amount);
     Chain.store('allowance:' + owner + ':' + spender, amount);
     
     // 批量数据使用JSON存储
     let data = {
       key1: value1,
       key2: value2
     };
     Chain.store('batch_data', JSON.stringify(data));
   }
   ```

4. Gas优化
   ```javascript
   // Gas使用优化
   function optimizedOperation() {
     // 减少存储操作
     let data = Chain.load('data');
     data = JSON.parse(data);
     data.value += 1;
     Chain.store('data', JSON.stringify(data));
     
     // 避免循环操作
     let total = Chain.load('total');
     Chain.store('total', String(Number(total) + value));
   }
   ```

5. 安全建议
   ```javascript
   // 安全检查示例
   function secureOperation(params) {
     // 权限检查
     let owner = Chain.load('owner');
     if (Chain.msg.sender !== owner) {
       throw 'No permission';
     }
     
     // 数值检查
     if (typeof params.value !== 'string' || !/^\d+$/.test(params.value)) {
       throw 'Invalid number format';
     }
     
     // 地址验证
     if (!Chain.isValidAddress(params.address)) {
       throw 'Invalid address';
     }
     
     // 状态检查
     if (Chain.load('paused') === 'true') {
       throw 'Contract is paused';
     }
   }
   ```