Handle getter functions for public state variables

Getter functions that are generated by the solidity
compiler do not wrap their return value in a tuple
like other functions do.
This commit is contained in:
Mark Spanbroek 2024-02-05 11:48:45 +01:00 committed by markspanbroek
parent b78463a299
commit 14a7485a88
3 changed files with 27 additions and 2 deletions

View File

@ -138,6 +138,13 @@ func getParameterTuple(procedure: NimNode): NimNode =
tupl.add name tupl.add name
return tupl return tupl
func isGetter(procedure: NimNode): bool =
let pragmas = procedure[4]
for pragma in pragmas:
if pragma.eqIdent "getter":
return true
false
func isConstant(procedure: NimNode): bool = func isConstant(procedure: NimNode): bool =
let pragmas = procedure[4] let pragmas = procedure[4]
for pragma in pragmas: for pragma in pragmas:
@ -145,6 +152,8 @@ func isConstant(procedure: NimNode): bool =
return true return true
elif pragma.eqIdent "pure": elif pragma.eqIdent "pure":
return true return true
elif pragma.eqIdent "getter":
return true
false false
func isMultipleReturn(returnType: NimNode): bool = func isMultipleReturn(returnType: NimNode): bool =
@ -166,6 +175,7 @@ func addContractCall(procedure: var NimNode) =
let function = $basename(procedure[0]) let function = $basename(procedure[0])
let parameters = getParameterTuple(procedure) let parameters = getParameterTuple(procedure)
let returnType = procedure[3][0] let returnType = procedure[3][0]
let isGetter = procedure.isGetter
procedure.addOverrides() procedure.addOverrides()
@ -173,7 +183,7 @@ func addContractCall(procedure: var NimNode) =
if returnType.kind == nnkEmpty: if returnType.kind == nnkEmpty:
quote: quote:
await call(`contract`, `function`, `parameters`, overrides) await call(`contract`, `function`, `parameters`, overrides)
elif returnType.isMultipleReturn: elif returnType.isMultipleReturn or isGetter:
quote: quote:
return await call( return await call(
`contract`, `function`, `parameters`, `returnType`, overrides `contract`, `function`, `parameters`, `returnType`, overrides
@ -193,7 +203,10 @@ func addContractCall(procedure: var NimNode) =
else: else:
quote: quote:
when typeof(result) isnot Confirmable: when typeof(result) isnot Confirmable:
{.error: "unexpected return type, missing {.view.} or {.pure.} ?".} {.error:
"unexpected return type, " &
"missing {.view.}, {.pure.} or {.getter.} ?"
.}
return await send(`contract`, `function`, `parameters`, overrides) return await send(`contract`, `function`, `parameters`, overrides)
procedure[6] = procedure[6] =
@ -229,6 +242,7 @@ macro contract*(procedure: untyped{nkProcDef|nkMethodDef}): untyped =
template view* {.pragma.} template view* {.pragma.}
template pure* {.pragma.} template pure* {.pragma.}
template getter* {.pragma.}
proc subscribe*[E: Event](contract: Contract, proc subscribe*[E: Event](contract: Contract,
_: type E, _: type E,

View File

@ -53,3 +53,11 @@ suite "Contract return values":
let values = await contract.getDynamics() let values = await contract.getDynamics()
check values.a == ("1", 2.u256) check values.a == ("1", 2.u256)
check values.b == ("3", 4.u256) check values.b == ("3", 4.u256)
test "handles static size struct as a public state variable":
proc staticVariable(contract: TestReturns): Static {.contract, getter.}
check (await contract.staticVariable()) == (1.u256, 2.u256)
test "handles dynamic size struct as a public state variable":
proc dynamicVariable(contract: TestReturns): Dynamic {.contract, getter.}
check (await contract.dynamicVariable()) == ("3", 4.u256)

View File

@ -11,6 +11,9 @@ contract TestReturns {
uint256 b; uint256 b;
} }
StaticStruct public staticVariable = StaticStruct(1, 2);
DynamicStruct public dynamicVariable = DynamicStruct("3", 4);
function getStatic() external pure returns (StaticStruct memory) { function getStatic() external pure returns (StaticStruct memory) {
return StaticStruct(1, 2); return StaticStruct(1, 2);
} }