diff --git a/manager/eris-mint/evm/snative.go b/manager/eris-mint/evm/snative.go index 92adbf300c5b339dfb33fdcc5903ffac2587e137..c03d2bcd7dfab9515ec798454ef53dc6b1206831 100644 --- a/manager/eris-mint/evm/snative.go +++ b/manager/eris-mint/evm/snative.go @@ -187,6 +187,12 @@ func SNativeContracts() map[string]*SNativeContractDescription { contractMap := make(map[string]*SNativeContractDescription, len(contracts)) for _, contract := range contracts { + if _, ok := contractMap[contract.Name]; ok { + // If this happens we have a pseudo compile time error that will be caught + // on native.go init() + panic(fmt.Errorf("Duplicate contract with name %s defined. " + + "Contract names must be unique.", contract.Name)) + } contractMap[contract.Name] = contract } return contractMap diff --git a/util/snatives/templates/solidity_templates.go b/util/snatives/templates/solidity_templates.go index 2f7d45fe35c416018754c850143de21a73b32e17..cc6cabd2d953766acb24de1a177c41ee4c30e3af 100644 --- a/util/snatives/templates/solidity_templates.go +++ b/util/snatives/templates/solidity_templates.go @@ -25,9 +25,10 @@ import ( const contractTemplateText = `/** [[.Comment]] -* @dev These functions can be accessed as if this contract were deployed at the address [[.Address]]. -* @dev For readability you may wish to define the following constant to refer to the SNative contract: -* @dev address constant [[.Name]]ContractAddress = [[.Address]] +* @dev These functions can be accessed as if this contract were deployed at a special address ([[.Address]]). +* @dev This special address is defined as the last 20 bytes of the sha3 hash of the the contract name. +* @dev To instantiate the contract use: +* @dev [[.Name]] [[.InstanceName]] = [[.Name]](address(sha3("[[.Name]]"))); */ contract [[.Name]] {[[range .Functions]] [[.SolidityIndent 1]] @@ -69,11 +70,30 @@ type solidityFunction struct { *vm.SNativeFunctionDescription } +// +// Contract +// + // Create a templated solidityContract from an SNative contract description func NewSolidityContract(contract *vm.SNativeContractDescription) *solidityContract { return &solidityContract{contract} } +func (contract *solidityContract) Comment() string { + return comment(contract.SNativeContractDescription.Comment) +} + +// Get a version of the contract name to be used for an instance of the contract +func (contract *solidityContract) InstanceName() string { + // Hopefully the contract name is UpperCamelCase. If it's not, oh well, this + // is meant to be illustrative rather than cast iron compilable + instanceName := strings.ToLower(contract.Name[:1]) + contract.Name[1:] + if instanceName == contract.Name { + return "contractInstance" + } + return instanceName +} + func (contract *solidityContract) Address() string { return fmt.Sprintf("0x%x", contract.SNativeContractDescription.Address()) @@ -98,6 +118,10 @@ func (contract *solidityContract) Functions() []*solidityFunction { return solidityFunctions } +// +// Function +// + // Create a templated solidityFunction from an SNative function description func NewSolidityFunction(function *vm.SNativeFunctionDescription) *solidityFunction { return &solidityFunction{function} @@ -133,9 +157,11 @@ func (function *solidityFunction) solidity(indentLevel uint) (string, error) { return buf.String(), nil } -func (contract *solidityContract) Comment() string { - return comment(contract.SNativeContractDescription.Comment) -} + +// +// Contract +// + func comment(comment string) string { commentLines := make([]string, 0, 5)