Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

varied tractor cleanups #839

Merged
merged 1 commit into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions protocol/contracts/C.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ library C {
uint80 internal constant SLOT_SIZE = 32;
uint80 internal constant ARGS_START_INDEX = SELECTOR_SIZE + SLOT_SIZE;
uint80 internal constant ADDR_SLOT_OFFSET = 12;
// Special index to indicate the data to copy is the publisher address.
uint80 internal constant PUBLISHER_COPY_INDEX = type(uint80).max;
// Special index to indicate the data to copy is the operator address.
uint80 internal constant OPERATOR_COPY_INDEX = type(uint80).max - 1;

function getSeasonPeriod() internal pure returns (uint256) {
Expand Down
71 changes: 36 additions & 35 deletions protocol/contracts/beanstalk/farm/TractorFacet.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/// SPDX-License-Identifier: MIT
/**
* SPDX-License-Identifier: MIT
**/

pragma solidity ^0.7.6;
pragma experimental ABIEncoderV2;
Expand All @@ -12,29 +14,21 @@ import {AdvancedFarmCall, LibFarm} from "../../libraries/LibFarm.sol";
import {LibBytes} from "contracts/libraries/LibBytes.sol";
/**
* @title TractorFacet handles tractor and blueprint operations.
* @author 0xm00neth, funderberker
* @author funderberker, 0xm00neth
*/
contract TractorFacet {
using LibBytes for bytes32;
using SafeMath for uint256;

/**********/
/* Events */
/**********/

/// @dev Emitted on publishRequisition()
event PublishRequisition(LibTractor.Requisition requisition);

/// @dev Emitted on cancelBlueprint()
event CancelBlueprint(bytes32 blueprintHash);

/// @dev Emitted on tractor()
event Tractor(address indexed operator, bytes32 blueprintHash);

/*************/
/* Modifiers */
/*************/

/**
* @notice Ensure requisition hash matches blueprint data and signer is publisher.
*/
modifier verifyRequisition(LibTractor.Requisition calldata requisition) {
bytes32 blueprintHash = LibTractor._getBlueprintHash(requisition.blueprint);
require(blueprintHash == requisition.blueprintHash, "TractorFacet: invalid hash");
Expand All @@ -46,7 +40,9 @@ contract TractorFacet {
_;
}

/// @notice Check blueprint nonce, increment nonce, handle active publisher.
/**
* @notice Verify nonce and time are acceptable, increment nonce, set publisher, clear publisher.
*/
modifier runBlueprint(LibTractor.Requisition calldata requisition) {
require(
LibTractor._getBlueprintNonce(requisition.blueprintHash) <
Expand All @@ -64,20 +60,18 @@ contract TractorFacet {
LibTractor._resetPublisher();
}

/******************/
/* User Functions */
/******************/

/// @notice Publish new blueprint
/// Emits {PublishRequisition} event
/**
* @notice Publish a new blueprint by emitting its data in an event.
*/
function publishRequisition(
LibTractor.Requisition calldata requisition
) external verifyRequisition(requisition) {
emit PublishRequisition(requisition);
}

/// @notice Destroy existing blueprint
/// Emits {CancelBlueprint} event
/**
* @notice Destroy existing blueprint
*/
function cancelBlueprint(
LibTractor.Requisition calldata requisition
) external verifyRequisition(requisition) {
Expand All @@ -86,8 +80,9 @@ contract TractorFacet {
emit CancelBlueprint(requisition.blueprintHash);
}

/// @notice Tractor Operation
/// Emits {Tractor} event
/**
* @notice Execute a Tractor blueprint as an operator.
*/
function tractor(
LibTractor.Requisition calldata requisition,
bytes memory operatorData
Expand All @@ -113,8 +108,6 @@ contract TractorFacet {
uint80 pasteCallIndex = operatorPasteInstr.getIndex1();
require(calls.length > pasteCallIndex, "Tractor: pasteCallIndex OOB");

// note: calls[..] reverts if operatorPasteInstr.getPasteCallIndex()
// is an invalid index.
LibBytes.pasteBytesTractor(
operatorPasteInstr,
operatorData,
Expand All @@ -125,22 +118,26 @@ contract TractorFacet {
results = new bytes[](calls.length);
for (uint256 i = 0; i < calls.length; ++i) {
require(calls[i].callData.length != 0, "Tractor: empty AdvancedFarmCall");
results[i] = LibFarm._advancedFarmMem(calls[i], results);
results[i] = LibFarm._advancedFarm(calls[i], results);
}
emit Tractor(msg.sender, requisition.blueprintHash);
}

/// @notice get counter count
/// @return count counter count
/**
* @notice Get current counter value.
* @return count Counter value
*/
function getCounter(bytes32 counterId) public view returns (uint256 count) {
return
LibTractor._tractorStorage().blueprintCounters[
LibTractor._tractorStorage().activePublisher
][counterId];
}

/// @notice update counter count
/// @return count counter count
/**
* @notice Update counter value.
* @return count New value of counter
*/
function updateCounter(
bytes32 counterId,
LibTractor.CounterUpdateType updateType,
Expand All @@ -158,14 +155,18 @@ contract TractorFacet {
return newCount;
}

/// @notice return current blueprint nonce
/// @return nonce current blueprint nonce
/**
* @notice Get current blueprint nonce.
* @return nonce current blueprint nonce
*/
function getBlueprintNonce(bytes32 blueprintHash) external view returns (uint256) {
return LibTractor._getBlueprintNonce(blueprintHash);
}

/// @notice return EIP712 hash of the blueprint
/// @return hash calculated Blueprint hash
/**
* @notice Get EIP712 compliant hash of the blueprint.
* @return hash Hash of Blueprint
*/
function getBlueprintHash(
LibTractor.Blueprint calldata blueprint
) external view returns (bytes32) {
Expand Down
38 changes: 3 additions & 35 deletions protocol/contracts/libraries/LibFarm.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,58 +24,26 @@ struct AdvancedFarmCall {

library LibFarm {
function _advancedFarm(
AdvancedFarmCall calldata data,
bytes[] memory returnData
) internal returns (bytes memory result) {
bytes1 pipeType = data.clipboard[0];
// 0x00 -> Static Call - Execute static call
// else > Advanced Call - Use clipboard on and execute call
if (pipeType == 0x00) {
result = _farm(data.callData);
} else {
bytes memory callData = LibClipboard.useClipboard(
data.callData,
data.clipboard,
returnData
);
result = _farmMem(callData);
}
}

// solidity kind of the worst for this
function _advancedFarmMem(
AdvancedFarmCall memory data,
bytes[] memory returnData
) internal returns (bytes memory result) {
bytes1 pipeType = data.clipboard[0];
// 0x00 -> Static Call - Execute static call
// else > Advanced Call - Use clipboard on and execute call
if (pipeType == 0x00) {
result = _farmMem(data.callData);
result = _farm(data.callData);
} else {
bytes memory callData = LibClipboard.useClipboard(
data.callData,
data.clipboard,
returnData
);
result = _farmMem(callData);
result = _farm(callData);
}
}

// delegatecall a Beanstalk function using calldata data
function _farm(bytes calldata data) internal returns (bytes memory result) {
bytes4 selector;
bool success;
assembly {
selector := calldataload(data.offset)
}
address facet = LibFunction.facetForSelector(selector);
(success, result) = facet.delegatecall(data);
LibFunction.checkReturn(success, result);
}

// delegatecall a Beanstalk function using memory data
function _farmMem(bytes memory data) internal returns (bytes memory result) {
function _farm(bytes memory data) internal returns (bytes memory result) {
bytes4 selector;
bool success;
assembly {
Expand Down
79 changes: 48 additions & 31 deletions protocol/contracts/libraries/LibTractor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {C} from "contracts/C.sol";

/**
* @title Lib Tractor
* @author 0xm00neth, funderbrker
* @author funderbrker, 0xm00neth
**/
library LibTractor {
// 0x7efbaaac9214ca1879e26b4df38e29a72561affb741bba775ce66d5bb6a82a07
Expand Down Expand Up @@ -49,77 +49,93 @@ library LibTractor {
uint256 endTime;
}

// Requisition stores blueprint, hash, and signature, which enables verification.
/**
* @notice Stores blueprint, hash, and signature, which enables verification.
*/
struct Requisition {
Blueprint blueprint;
bytes32 blueprintHash; // including this is not strictly necessary, but helps avoid hashing more than once on chain
bytes signature;
}

/// @notice get tractor storage from storage
/// @return ts TractorStorage
/**
* @notice Get tractor storage from storage.
* @return ts Storage object containing tractor data
*/
function _tractorStorage() internal pure returns (TractorStorage storage ts) {
// keccak256("diamond.storage.tractor") == 0x7efbaaac9214ca1879e26b4df38e29a72561affb741bba775ce66d5bb6a82a07
assembly {
ts.slot := 0x7efbaaac9214ca1879e26b4df38e29a72561affb741bba775ce66d5bb6a82a07
}
}

/// @notice increment the blueprint nonce by 1
/// @param blueprintHash blueprint hash
/**
* @notice Increment the blueprint nonce by 1.
* @param blueprintHash blueprint hash
*/
function _incrementBlueprintNonce(bytes32 blueprintHash) internal {
TractorStorage storage ts = _tractorStorage();
++ts.blueprintNonce[blueprintHash];
_tractorStorage().blueprintNonce[blueprintHash]++;
}

/// @notice cancel blueprint
/// @dev set blueprintNonce to type(uint256).max
/// @param blueprintHash blueprint hash
/**
* @notice Cancel blueprint.
* @dev set blueprintNonce to type(uint256).max
* @param blueprintHash blueprint hash
*/
function _cancelBlueprint(bytes32 blueprintHash) internal {
_tractorStorage().blueprintNonce[blueprintHash] = type(uint256).max;
}

/// @notice set blueprint publisher address
/// @param publisher blueprint publisher address
/**
* @notice Set blueprint publisher address.
* @param publisher blueprint publisher address
*/
function _setPublisher(address payable publisher) internal {
require(
uint160(bytes20(_tractorStorage().activePublisher)) <= 1,
"LibTractor: publisher already set"
);
_tractorStorage().activePublisher = publisher;
TractorStorage storage ts = _tractorStorage();
require(uint160(bytes20(ts.activePublisher)) <= 1, "LibTractor: publisher already set");
ts.activePublisher = publisher;
}

/// @notice reset blueprint publisher address
/**
* @notice Reset blueprint publisher address.
*/
function _resetPublisher() internal {
_tractorStorage().activePublisher = address(1);
}

/// @notice return current activePublisher address
/// @return publisher current activePublisher address
/** @notice Return current activePublisher address.
* @return publisher current activePublisher address
*/
function _getActivePublisher() internal view returns (address payable) {
return _tractorStorage().activePublisher;
}

/// @notice return current activePublisher address or msg.sender if no active blueprint
/// @return user to take actions on behalf of
/** @notice Return current activePublisher address or msg.sender if no active blueprint.
* @return user to take actions on behalf of
*/
function _user() internal view returns (address payable user) {
user = _getActivePublisher();
if (uint160(bytes20(user)) <= 1) {
user = msg.sender;
}
}

/// @notice get blueprint nonce
/// @param blueprintHash blueprint hash
/// @return nonce current blueprint nonce
/**
* @notice Get blueprint nonce.
* @param blueprintHash blueprint hash
* @return nonce current blueprint nonce
*/
function _getBlueprintNonce(bytes32 blueprintHash) internal view returns (uint256) {
return _tractorStorage().blueprintNonce[blueprintHash];
}

/// @notice calculates blueprint hash
/// @dev https://eips.ethereum.org/EIPS/eip-712
/// @param blueprint blueprint object
/// @return hash calculated Blueprint hash
/**
* @notice Calculates blueprint hash.
* @dev https://eips.ethereum.org/EIPS/eip-712
* @dev https://github.com/BeanstalkFarms/Beanstalk/pull/727#discussion_r1577293450
* @param blueprint blueprint object
* @return hash calculated Blueprint hash
*/
function _getBlueprintHash(Blueprint calldata blueprint) internal view returns (bytes32) {
return
_hashTypedDataV4(
Expand All @@ -138,6 +154,7 @@ library LibTractor {
}

/**
* @notice Hashes in an EIP712 compliant way.
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
Expand All @@ -151,7 +168,7 @@ library LibTractor {
}

/**
* @dev Returns the domain separator for the current chain.
* @notice Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
return
Expand Down
Loading