Closed iostat closed 7 months ago
@blinky3713 @safareli thoughts and comments would be highly appreciated
I suspect it's expected this functions to be generated by the web3 generator:
module Contracts.TCR where
constructor :: TransactionOptions NoPay ZeroAddress -> { plcr :: Address PLCRVotingAddress, params :: Address ParameterizerAddress } -> Web3 TransactionHash
in which case, It's not quite clear to how we are going to go from:
constructor(
address _plcrAddr,
address _paramsAddr
)
to
{ plcr :: Address PLCRVotingAddress
, params :: Address ParameterizerAddress
}
Actually rethinking this a little bit, it makes more sense to have purescript-web3 declare its own Address a
type over purescript-eth-core
's address, as that's a semantic introduced by ps-web3
and currently ps-web3
just reexport's ps-eth-core
's Address type.
@safareli Initially, the codegen can simply generate forall address1 address2. TxOptions ... -> { plcr :: Address address1, params :: Address address2 } -> Web3 TxHash
. Later on, the codegen can enhance solc
's ABI output with solc
's AST output which gives you the type of each parameter (i.e., you can distinguish whether it's declared as an address
or SomeContract
in the parameter list) which gives you the type of each parameter. Because Chanterelle expects you to keep a Haskell/PureScript module/contract naming scheme, you can be sure that if the argument is of, say, Parameterizer type, there's going be a ParameterizerAddress
generated by the codegen in Parameterizer's PureScript module. Because you are similarly expected to construct the contract with a Chanterelle deploy script, the codegen can import Contracts.Parameterizer
(or whatever the configured module prefix is) in Contracts.TCR
with the assumption that Parameterizer
is being codegen'd independently as part of Chanterelle invoking it.
Currently,
Address
is just a plain old type that can be passed around, and every ps-web3-generated contract call function just takes a TransactionOptions Payable/NoPay as its first argument. While this is really convenient, it also leads to potential for grossly incorrect code that still passes typechecking and compiles. For example,In this example, I can use
TransactionOptions
that send to a SomeERC20 contract while actually calling an function intended for a SomeERC721 contract, with nothing stopping me, and vice versa. Moreover, I can't determine the order of the arguments todoAThing
from the type alone. It gets even worse -- as the names of the parameters suggest, I wanted userAddress and otherUserAddress to be two different addresses, but, there's nothing stopping me from enforcing that userAddress and otherUserAddress are actually different addresses!On the other hand, by adding a phantom type, I can write doAThing in much more concrete and typesafe ways. For example, if I could write a signature like
I can now make my intentions very clear as to what the
Address
es are supposed to be, in addition to having the compiler enforce usage (a user ofdoAThing
would need to constructAddress user
andAddress otherUser
making room for error much lower -- yes they can still do two separatemkAddress
es but at least that's less likely to accidentally happen). Of course, this now meansTransactionOptions tokenUnit
has to becomeTransactionOptions tokenUnit addressType
(more correctly --TransactionOptions tokenUnit fromAddressType toAddressType
--fromAddressType
will be omitted for brevity), which is actually a great thing! The signatures oftransferFrom
can now change as well, making it much more difficult for me to call the ERC721 contract with an ERC20 address and vice-versa (again, i'd have to construct the address more explictly):Later on down the line, we could potentially have
purescript-web3-generator
read AST output fromsolc
to determine exactly what type of address each argument is, for instance, a TCR contract could go fromto
This also has the potential to be useful in Chanterelle's library WIP, where I can force a deployment script to deploy and link the correct library (a Library can still have PureScript code generated for the
foreign import data
, forcing a user to deploy or otherwise supply a library address tolinkLibrary
of the correct library type, reducing reliance on meticulous double-checking of code.This is naturally a very breaking change, so I propose this for a
purescript-web3
2.0 eventually.