Skip to content
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
10 changes: 10 additions & 0 deletions packages/cashc/src/semantic/SymbolTableTraversal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
ConsoleStatementNode,
ConsoleParameterNode,
ForNode,
SliceNode,
TupleAssignmentTarget,
} from '../ast/AST.js';
import AstTraversal from '../ast/AstTraversal.js';
Expand Down Expand Up @@ -202,6 +203,15 @@ export default class SymbolTableTraversal extends AstTraversal {
return node;
}

// Code generation evaluates the end before the start (element.split(end)[0].split(start)[1]), so the final use
// of a variable (where it is rolled instead of picked) has to be tracked in that same order
visitSlice(node: SliceNode): Node {
node.element = this.visit(node.element);
node.end = this.visit(node.end);
node.start = this.visit(node.start);
return node;
}

// When we enter a console statement,
visitConsoleStatement(node: ConsoleStatementNode): Node {
this.insideConsoleStatement = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Fixture } from '../../fixture-utils.js';

// .slice(start, end) evaluates end before start, so a variable used in both arguments is picked for end and
// rolled for start (instead of being rolled for end and then missing, or read from a stale slot, for start)
export const fixtures: Fixture[] = [
{
artifact: {
contractName: 'SliceVariableReuse',
constructorInputs: [],
abi: [{ name: 'spend', inputs: [{ name: 'data', type: 'bytes' }, { name: 'index', type: 'int' }] }],
bytecode:
// int next = index + 1;
'OP_OVER OP_1ADD '
// next = next + 1;
+ 'OP_DUP OP_1ADD '
// require(data.slice(next, next + 1) == 0x33);
+ 'OP_3DUP OP_NIP OP_1ADD OP_SPLIT OP_DROP OP_SWAP OP_SPLIT OP_NIP 33 OP_EQUALVERIFY '
// require(data.slice(index, index + 1) == 0x11);
+ 'OP_SWAP OP_2 OP_PICK OP_1ADD OP_SPLIT OP_DROP OP_ROT OP_SPLIT OP_NIP 11 OP_EQUAL '
// Cleanup
+ 'OP_NIP',
fingerprint: 'bee1541625c082916f1c0bed69773886d459872311414c0e46877ea1d37cdf43',
debug: {
bytecode: '788b768b6f778b7f757c7f770133887c52798b7f757b7f7701118777',
sourceMap: '3:19:3:24;:::28:1;4:15:4:19:0;:::23:1;5:16:5:37:0;;:33::41:1;:16::42;;:27::31:0;:16::42:1;;:46::50:0;:8::52:1;6:16:6:20:0;:34::39;;:::43:1;:16::44;;:27::32:0;:16::44:1;;:48::52:0;:8::54:1;2:42:7:5',
logs: [],
requires: [{ ip: 13, line: 5 }, { ip: 25, line: 6 }],
sourceTags: '25:25:sc',
},
},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
contract SliceVariableReuse() {
function spend(bytes data, int index) {
int next = index + 1;
next = next + 1;
require(data.slice(next, next + 1) == 0x33);
require(data.slice(index, index + 1) == 0x11);
}
}
Loading