我想知道用类型化语言(如Haskell或Idris)表达智能合约的最佳方法是什么(例如,这样你就可以编译它以在以太坊网络上运行)。我主要关心的是:什么样的类型可以捕获契约可以做的所有事情?
一个简单的解决方案是将契约定义为EthIO
类型的成员。这种类型将类似于Haskell的IO
,但它将包括区块链调用,而不是启用系统调用,也就是说,它将允许读写区块链的状态,调用其他契约,获取块数据等。
-- incrementer.contract
main: EthIO
main = do
x <- SREAD 0x123456789ABCDEF
SSTORE (x + 1) 0x123456789ABCDEF
这显然足以执行任何契约,但是:
太强大了。
将特别与以太坊区块链耦合。
根据这种观点,合同将被定义为一系列行为的折叠:
type Contract action state = {
act : UserID -> action -> state -> state,
init : state
}
因此,一个程序应该是这样的:
incrementer.contract
main : Contract
main = {
act _ _ state = state + 1,
init = 0
}
也就是说,您定义一个初始状态、一种操作类型,以及当用户提交操作时该状态如何更改。这将允许人们定义任何不涉及发送/接收资金的任意合同。大多数区块链都有某种货币,大多数有用的合同都以某种方式涉及金钱,所以这种类型的限制太大了。
通过将货币逻辑硬编码到上述类型中,可以使上述类型能够识别货币。因此,我们会得到这样的结果:
type Contract action state = {
act : UserID -> action -> state -> state,
init : state,
deposit : UserID -> Amount -> state -> state,
withdrawal : UserID -> Amount -> state -> Maybe state
}
也就是说,合同开发商需要明确定义如何处理货币存款和取款。这种类型足以定义任何可以与主机区块链的货币交互的自包含合约。可悲的是,这样的契约将无法与其他契约交互。在实践中,合同经常相互影响。例如,一个Exchange需要与其交换的Token合约进行通信,以查询余额等。
那么,让我们退一步,把保守解重写成这样:
type Contract = {
act : UserID -> Action -> Map ContractID State -> State,
init : State
}
在此定义下,act
函数不仅可以访问合约本身的状态,还可以访问相同区块链上所有其他合约的状态。由于每个合约都可以读取彼此的状态,因此可以很容易地在此基础上实现通信协议,因此,这种类型足以实现任意交互的合约。此外,如果区块链的货币本身实现为合约(可能使用包装器),那么该类型也足以处理货币,尽管没有在类型上硬编码。但这个解决方案有两个问题:
偷看对方合同的状态看起来很“hack "实现通信的方式;
现在我被蒙在鼓里。我知道我对这个问题没有正确的抽象,但我不确定它会是什么。看起来问题的根源在于我不能正确地捕捉交叉契约通信的现象。哪种具体类型更适合定义任意智能合约?