Skip to content

Commit

Permalink
Testing 195 additional testings (superfluid-org#220)
Browse files Browse the repository at this point in the history
* added validateContextStructLayout
* validate decoded ctx
* test noops masks
  • Loading branch information
hellwolf committed Jan 28, 2021
1 parent 9cd110a commit d758a67
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 89 deletions.
114 changes: 87 additions & 27 deletions packages/ethereum-contracts/contracts/mocks/AgreementMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,45 +173,107 @@ contract AgreementMock is AgreementBase {
return ctx;
}

event AppBeforeCallbackResult(bytes cbdata);

function callAppBeforeAgreementCreatedCallback(
event AppBeforeCallbackResult(
uint8 appLevel,
uint8 callType,
bytes4 agreementSelector,
bytes cbdata);

event AppAfterCallbackResult(
uint8 appLevel,
uint8 callType,
bytes4 agreementSelector);

function _callAppBeforeCallback(
ISuperApp app,
uint256 noopBit,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
private
{
ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
AgreementLibrary.CallbackInputs memory cbStates = AgreementLibrary.createCallbackInputs(
ISuperfluidToken(address(0)) /* token */,
address(app) /* account */,
0 /* agreementId */,
"" /* agreementData */
);
cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP;
cbStates.noopBit = noopBit;
bytes memory cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, ctx);
emit AppBeforeCallbackResult(cbdata);
newCtx = ctx;
emit AppBeforeCallbackResult(
context.appLevel,
context.callType,
context.agreementSelector,
cbdata);
}

function callAppAfterAgreementCreatedCallback(
function _callAppAfterAgreementCallback(
ISuperApp app,
uint256 noopBit,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
private returns (bytes memory newCtx)
{
ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
AgreementLibrary.CallbackInputs memory cbStates = AgreementLibrary.createCallbackInputs(
ISuperfluidToken(address(0)) /* token */,
address(app) /* account */,
0 /* agreementId */,
"" /* agreementData */
);
cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_CREATED_NOOP;
cbStates.noopBit = noopBit;
(, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, "", ctx);
require(ISuperfluid(msg.sender).isCtxValid(newCtx), "AgreementMock: ctx not valid after");
emit AppAfterCallbackResult(
context.appLevel,
context.callType,
context.agreementSelector);
}

function callAppBeforeAgreementCreatedCallback(
ISuperApp app,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
{
_callAppBeforeCallback(app, SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP, ctx);
return ctx;
}

function callAppAfterAgreementCreatedCallback(
ISuperApp app,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
{
return _callAppAfterAgreementCallback(app, SuperAppDefinitions.AFTER_AGREEMENT_CREATED_NOOP, ctx);
}

function callAppBeforeAgreementUpdatedCallback(
ISuperApp app,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
{
_callAppBeforeCallback(app, SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP, ctx);
return ctx;
}

function callAppAfterAgreementUpdatedCallback(
ISuperApp app,
bytes calldata ctx
)
external
validCtx(ctx)
returns (bytes memory newCtx)
{
return _callAppAfterAgreementCallback(app, SuperAppDefinitions.AFTER_AGREEMENT_UPDATED_NOOP, ctx);
}

function callAppBeforeAgreementTerminatedCallback(
Expand All @@ -222,15 +284,7 @@ contract AgreementMock is AgreementBase {
validCtx(ctx)
returns (bytes memory newCtx)
{
AgreementLibrary.CallbackInputs memory cbStates = AgreementLibrary.createCallbackInputs(
ISuperfluidToken(address(0)) /* token */,
address(app) /* account */,
0 /* agreementId */,
"" /* agreementData */
);
cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP;
bytes memory cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, ctx);
emit AppBeforeCallbackResult(cbdata);
_callAppBeforeCallback(app, SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP, ctx);
newCtx = ctx;
}

Expand All @@ -242,15 +296,21 @@ contract AgreementMock is AgreementBase {
validCtx(ctx)
returns (bytes memory newCtx)
{
/* ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
AgreementLibrary.CallbackInputs memory cbStates = AgreementLibrary.createCallbackInputs(
ISuperfluidToken(address(0)) /* token */,
address(app) /* account */,
0 /* agreementId */,
"" /* agreementData */
ISuperfluidToken(address(0)) // token,
address(app) // account,
0 // agreementId,
"" // agreementData
);
cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP;
(, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, "", ctx);
require(ISuperfluid(msg.sender).isCtxValid(newCtx), "AgreementMock: ctx not valid after");
emit AppAfterCallbackResult(
context.appLevel,
context.callType,
context.agreementSelector); */
return _callAppAfterAgreementCallback(app, SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP, ctx);
}

modifier validCtx(bytes memory ctx) {
Expand Down
23 changes: 18 additions & 5 deletions packages/ethereum-contracts/contracts/mocks/SuperAppMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ contract SuperAppMock is ISuperApp {
* Test App Actions
**************************************************************************/

event NoopEvent();
event NoopEvent(
uint8 appLevel,
uint8 callType,
bytes4 agreementSelector);

function actionNoop(bytes calldata ctx) external validCtx(ctx) returns (bytes memory newCtx) {
emit NoopEvent();
ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
emit NoopEvent(
context.appLevel,
context.callType,
context.agreementSelector);
return ctx;
}

Expand All @@ -50,7 +57,10 @@ contract SuperAppMock is ISuperApp {
{
ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
assert(context.msgSender == expectedMsgSender);
emit NoopEvent();
emit NoopEvent(
context.appLevel,
context.callType,
context.agreementSelector);
return ctx;
}

Expand Down Expand Up @@ -235,7 +245,6 @@ contract SuperAppMock is ISuperApp {
returns (bytes memory cbdata)
{
if (_nextCallbackAction.actionType == NextCallbackActionType.Noop) {
//emit NoopEvent();
return "Noop";
} else if (_nextCallbackAction.actionType == NextCallbackActionType.Assert) {
assert(false);
Expand All @@ -254,8 +263,12 @@ contract SuperAppMock is ISuperApp {
private
returns (bytes memory newCtx)
{
ISuperfluid.Context memory context = ISuperfluid(msg.sender).decodeCtx(ctx);
if (_nextCallbackAction.actionType == NextCallbackActionType.Noop) {
emit NoopEvent();
emit NoopEvent(
context.appLevel,
context.callType,
context.agreementSelector);
return ctx;
} else if (_nextCallbackAction.actionType == NextCallbackActionType.Assert) {
assert(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ contract SuperTokenFactoryStorageLayoutTester is SuperTokenFactoryBase {
{
}

// @dev Make sure the storage layout never change over the course of the development
function validateStorageLayout() external pure {
uint256 slot;
uint256 offset;
Expand All @@ -27,6 +28,7 @@ contract SuperTokenFactoryStorageLayoutTester is SuperTokenFactoryBase {
require (slot == 0 && offset == 2, "_superTokenLogic changed location");
}

// dummy impl
function createSuperTokenLogic(ISuperfluid)
external pure override
returns (address)
Expand Down
13 changes: 5 additions & 8 deletions packages/ethereum-contracts/contracts/mocks/SuperTokenMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@ contract SuperTokenStorageLayoutTester is SuperToken {
{
}

function getLastSuperTokenStorageSlot() external pure returns (uint slot) {
assembly { slot:= _reserve19.slot }
}

/**
* Upgradability
*/

// @dev Make sure the storage layout never change over the course of the development
function validateStorageLayout() external pure {
uint256 slot;
uint256 offset;
Expand Down Expand Up @@ -74,6 +67,10 @@ contract SuperTokenStorageLayoutTester is SuperToken {
assembly { slot:= _reserve19.slot offset := _reserve19.offset }
require (slot == 31 && offset == 0, "_reserve19 changed location");
}

function getLastSuperTokenStorageSlot() external pure returns (uint slot) {
assembly { slot:= _reserve19.slot }
}
}

contract SuperTokenMock is SuperToken {
Expand Down
87 changes: 79 additions & 8 deletions packages/ethereum-contracts/contracts/mocks/SuperfluidMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,14 @@ import {
import { CallUtils } from "../utils/CallUtils.sol";


contract SuperfluidMock is Superfluid {

contract SuperfluidUpgradabilityTester is Superfluid {

constructor(bool nonUpgradable)
Superfluid(nonUpgradable)
constructor() Superfluid(false)
// solhint-disable-next-line no-empty-blocks
{
}

/**
* Upgradability
*/

// @dev Make sure the storage layout never change over the course of the development
function validateStorageLayout()
external pure
{
Expand Down Expand Up @@ -51,6 +46,82 @@ contract SuperfluidMock is Superfluid {
require (slot == 6 && offset == 0, "_ctxStamp changed location");
}

// @dev Make sure the context struct layout never change over the course of the development
function validateContextStructLayout()
external pure
{
// context.appLevel
{
Context memory context;
assembly { mstore(add(context, mul(32, 0)), 42) }
require(context.appLevel == 42, "appLevel changed location");
}
// context.callType
{
Context memory context;
assembly { mstore(add(context, mul(32, 1)), 42) }
require(context.callType == 42, "callType changed location");
}
// context.timestamp
{
Context memory context;
assembly { mstore(add(context, mul(32, 2)), 42) }
require(context.timestamp == 42, "timestamp changed location");
}
// context.msgSender
{
Context memory context;
assembly { mstore(add(context, mul(32, 3)), 42) }
require(context.msgSender == address(42), "msgSender changed location");
}
// context.agreementSelector
{
Context memory context;
// be aware of the bytes4 endianness
assembly { mstore(add(context, mul(32, 4)), shl(224, 0xdeadbeef)) }
require(context.agreementSelector == bytes4(uint32(0xdeadbeef)), "agreementSelector changed location");
}
// context.userData
{
Context memory context;
context.userData = new bytes(42);
uint256 dataOffset;
assembly { dataOffset := mload(add(context, mul(32, 5))) }
require(dataOffset != 0, "userData offset is zero");
uint256 dataLen;
assembly { dataLen := mload(dataOffset) }
require(dataLen == 42, "userData changed location");
}
// context.appAllowanceGranted
{
Context memory context;
assembly { mstore(add(context, mul(32, 6)), 42) }
require(context.appAllowanceGranted == 42, "appAllowanceGranted changed location");
}
// context.appAllowanceGranted
{
Context memory context;
assembly { mstore(add(context, mul(32, 7)), 42) }
require(context.appAllowanceWanted == 42, "appAllowanceWanted changed location");
}
// context.appAllowanceGranted
{
Context memory context;
assembly { mstore(add(context, mul(32, 8)), 42) }
require(context.appAllowanceUsed == 42, "appAllowanceUsed changed location");
}
}
}

contract SuperfluidMock is Superfluid {


constructor(bool nonUpgradable)
Superfluid(nonUpgradable)
// solhint-disable-next-line no-empty-blocks
{
}

function ctxFunc1(uint256 n, bytes calldata ctx)
external pure
returns (uint256, bytes memory)
Expand Down
Loading

0 comments on commit d758a67

Please sign in to comment.