diff --git a/Sources/IRGen/Function/IULIACallerCapabilityChecks.swift b/Sources/IRGen/Function/IULIACallerCapabilityChecks.swift deleted file mode 100644 index ee43173a..00000000 --- a/Sources/IRGen/Function/IULIACallerCapabilityChecks.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// IULIACallerCapabilityChecks.swift -// IRGen -// -// Created by Franklin Schrans on 4/28/18. -// - -import AST - -/// Checks whether the caller of a function has appropriate caller capabilities. -struct IULIACallerCapabilityChecks { - var callerCapabilities: [CallerCapability] - - func rendered(functionContext: FunctionContext) -> String { - let environment = functionContext.environment - - let checks = callerCapabilities.compactMap { callerCapability -> String? in - guard !callerCapability.isAny else { return nil } - - let type = environment.type(of: callerCapability.identifier.name, enclosingType: functionContext.enclosingTypeName) - let offset = environment.propertyOffset(for: callerCapability.name, enclosingType: functionContext.enclosingTypeName)! - - switch type { - case .fixedSizeArrayType(_, let size): - return (0.. String { - // Dynamically check the caller has appropriate caller capabilities. - let callerCapabilityChecks = IULIACallerCapabilityChecks(callerCapabilities: callerCapabilities).rendered(functionContext: functionContext) let body = renderBody(functionDeclaration.body, functionContext: functionContext) // Assign a caller capaiblity binding to a local variable. @@ -117,7 +115,7 @@ struct IULIAFunctionBody { capabilityBindingDeclaration = "" } - return "\(callerCapabilityChecks)\(capabilityBindingDeclaration)\(body)" + return "\(capabilityBindingDeclaration)\(body)" } func renderBody(_ statements: S, functionContext: FunctionContext) -> String where S.Element == AST.Statement, S.Index == Int { diff --git a/Sources/IRGen/IULIAContract.swift b/Sources/IRGen/IULIAContract.swift index a45ca857..b2fcbe02 100644 --- a/Sources/IRGen/IULIAContract.swift +++ b/Sources/IRGen/IULIAContract.swift @@ -37,7 +37,7 @@ struct IULIAContract { let publicFunctions = functions.filter { $0.functionDeclaration.isPublic } // Create a function selector, to determine which function is called in the Ethereum transaction. - let functionSelector = IULIAFunctionSelector(functions: publicFunctions) + let functionSelector = IULIAFunctionSelector(functions: publicFunctions, enclosingType: contractDeclaration.identifier.name, environment: environment) let selectorCode = functionSelector.rendered().indented(by: 6) // Generate code for each function in the structs. diff --git a/Sources/IRGen/Runtime/IULIAFunctionSelector.swift b/Sources/IRGen/Runtime/IULIAFunctionSelector.swift index 2a552df4..aaf152ca 100644 --- a/Sources/IRGen/Runtime/IULIAFunctionSelector.swift +++ b/Sources/IRGen/Runtime/IULIAFunctionSelector.swift @@ -6,10 +6,13 @@ // import CryptoSwift +import AST /// Runtime code in IULIA which determines which function to call based on the Ethereum's transaction payload. struct IULIAFunctionSelector { var functions: [IULIAFunction] + var enclosingType: RawTypeIdentifier + var environment: Environment func rendered() -> String { let cases = renderCases() @@ -30,7 +33,7 @@ struct IULIAFunctionSelector { return """ case \(functionHash) /* \(function.mangledSignature()) */ { - \(renderCaseBody(function: function)) + \(renderCaseBody(function: function).indented(by: 2)) } """ @@ -38,6 +41,10 @@ struct IULIAFunctionSelector { } func renderCaseBody(function: IULIAFunction) -> String { + // Dynamically check the caller has appropriate caller capabilities. + let callerCapabilities = function.callerCapabilities + let callerCapabilityChecks = IULIACallerCapabilityChecks(callerCapabilities: callerCapabilities).rendered(enclosingType: enclosingType, environment: environment) + let arguments = function.parameterCanonicalTypes.enumerated().map { arg -> String in let (index, type) = arg switch type { @@ -50,10 +57,49 @@ struct IULIAFunctionSelector { if let resultType = function.resultCanonicalType { switch resultType { - case .address, .uint256, .bytes32: return IULIARuntimeFunction.return32Bytes(value: call) + case .address, .uint256, .bytes32: return callerCapabilityChecks + "\n" + IULIARuntimeFunction.return32Bytes(value: call) } } - return call + return callerCapabilityChecks + "\n" + call } } + +/// Checks whether the caller of a function has appropriate caller capabilities. +struct IULIACallerCapabilityChecks { + var callerCapabilities: [CallerCapability] + + func rendered(enclosingType: RawTypeIdentifier, environment: Environment) -> String { + let checks = callerCapabilities.compactMap { callerCapability -> String? in + guard !callerCapability.isAny else { return nil } + + let type = environment.type(of: callerCapability.identifier.name, enclosingType: enclosingType) + let offset = environment.propertyOffset(for: callerCapability.name, enclosingType: enclosingType)! + + switch type { + case .fixedSizeArrayType(_, let size): + return (0..